spitewaste 0.1.004 → 0.1.009

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,34 +1,40 @@
1
- import bits ; bitwise_and, bitwise_or, bitwise_xor
2
- import string ; isalpha, strcat, strunpack
3
-
4
1
  ;;; Case conversion
5
2
 
6
- upcase: :strunpack push 0 ; tally
7
- _upcase_loop:
8
- swap dup jz _upcase_done
9
- dup :isalpha jz _upcase_cat
10
- push 95 :bitwise_and
11
- _upcase_cat:
12
- :strcat jump _upcase_loop
13
-
14
- _upcase_done: pop ret
3
+ import bits ; band, bor, bxor
4
+ import string ; isalpha, strcat, strunpack
15
5
 
16
- downcase: :strunpack push 0 ; tally
17
- _downcase_loop:
18
- swap dup jz _downcase_done
19
- dup :isalpha jz _downcase_cat
20
- push 32 :bitwise_or
21
- _downcase_cat:
22
- :strcat jump _downcase_loop
6
+ ; The case conversion functions all behave very similarly, differing only in
7
+ ; how they modify the ordinal value V of a character to be kept.
8
+ ; upcase is V & 95, downcase is V | 32, and swapcase is V ^ 32.
9
+ $casefun(case, op) {
10
+ :strunpack push 0 ; get characters on stack and initialize accumulator
11
+ _`case`_loop: swap dup jz _`case`_done dup :isalpha jz _`case`_cat `op`
12
+ _`case`_cat: :strcat jump _`case`_loop
13
+ _`case`_done: pop ret
14
+ }
23
15
 
24
- _downcase_done: pop ret
16
+ ; returns string S with all alphabetical characters capitalized
17
+ ; [S] => [S']
18
+ ;
19
+ ; [""] => [""]
20
+ ; ["abc"] => ["ABC"]
21
+ ; ["123"] => ["123"]
22
+ ; ["Abc123Def"] => ["ABC123DEF"]
23
+ upcase: $casefun(upcase, push 0x5F :band)
25
24
 
26
- swapcase: :strunpack push 0 ; tally
27
- _swapcase_loop:
28
- swap dup jz _swapcase_done
29
- dup :isalpha jz _swapcase_cat
30
- push 32 :bitwise_xor
31
- _swapcase_cat:
32
- :strcat jump _swapcase_loop
25
+ ; returns string S with all alphabetical characters lower-cased
26
+ ; [S] => [S']
27
+ ;
28
+ ; [""] => [""]
29
+ ; ["ABC"] => ["abc"]
30
+ ; ["123"] => ["123"]
31
+ ; ["aBC123dEF"] => ["abc123def"]
32
+ downcase: $casefun(downcase, push 0x20 :bor)
33
33
 
34
- _swapcase_done: pop ret
34
+ ; returns string S with the case of all alphabetical characters swapped
35
+ ; [S] => [S']
36
+ ;
37
+ ; [""] => [""]
38
+ ; ["FooBar"] => ["fOObAR"]
39
+ ; ["Abc123deF"] => ["aBC123DEf"]
40
+ swapcase: $casefun(swapcase, push 0x20 :bxor)
@@ -0,0 +1 @@
1
+ {"fun":{"palindrome?":{"full":"returns whether the string S is the same forwards and backwards\n[S] => [0 | 1]\n\n[\"racecar\"] => [1]\n[\"divider\"] => [0]\n[\"redivider\"] => [1]\n","desc":"returns whether the string S is the same forwards and backwards","effect":"[S] => [0 | 1]","cases":[[[504736985444594],[1]],[[504874701534436],[0]],[[8271867109940212466],[1]]]},"anagrams?":{"full":"returns whether the strings S and T are composed of the same characters\n[S T] => [0 | 1]\n\n[\"allergy\" \"gallery\"] => [1]\n[\"largely\" \"regally\"] => [1]\n[\"foo\" \"bar\"] => [0]\n","desc":"returns whether the strings S and T are composed of the same characters","effect":"[S T] => [0 | 1]","cases":[[[535733496133217,536107978272999],[1]],[[535901809455340,535903675740914],[1]],[[1832934,1880290],[0]]]},"isop":{"full":"returns the sum of the alphabetical characters in string S where A=1, B=2...\n[S] => [sum]\n\n[\"Math\"] => [42]\n[\"wizards\"] => [100]\n[\"AbCd\"] => [10]\n","desc":"returns the sum of the alphabetical characters in string S where A=1, B=2...","effect":"[S] => [sum]","cases":[[[220016845],[42]],[[509242129691895],[100]],[[210825537],[10]]]},"collatz":{"full":"returns the elements of the Collatz sequence for integer N as a pseudo-array\n[N] => [A]\n\n[1] => [1 1]\n[2] => [2 1 2]\n[3] => [3 10 5 16 8 4 2 1 8]\n[4] => [4 2 1 3]\n[5] => [5 16 8 4 2 1 6]\n","desc":"returns the elements of the Collatz sequence for integer N as a pseudo-array","effect":"[N] => [A]","cases":[[[1],[1,1]],[[2],[2,1,2]],[[3],[3,10,5,16,8,4,2,1,8]],[[4],[4,2,1,3]],[[5],[5,16,8,4,2,1,6]]]}},"math":{"pow":{"full":"returns B raised to the power E\n[B E] => [B**E]\n\n[0 0] => [1], [0 9] => [0], [9 0] => [1]\n[3 2] => [9], [2 3] => [8], [7 4] => [2401]\n[-2 3] => [-8] [-5 0] => [1] [-4 4] => [256]\n","desc":"returns B raised to the power E","effect":"[B E] => [B**E]","cases":[[[0,0],[1]],[[0,9],[0]],[[9,0],[1]],[[3,2],[9]],[[2,3],[8]],[[7,4],[2401]],[[-2,3],[-8]],[[-5,0],[1]],[[-4,4],[256]]]},"factorial":{"full":"returns the product of the integers from 1 to N, with 0! defined to be 1\n[N] => [N!]\n\n[0] => [1], [1] => [1], [2] => [2]\n[3] => [6], [5] => [120], [10] => [3628800]\n","desc":"returns the product of the integers from 1 to N, with 0! defined to be 1","effect":"[N] => [N!]","cases":[[[0],[1]],[[1],[1]],[[2],[2]],[[3],[6]],[[5],[120]],[[10],[3628800]]]},"isqrt":{"full":"returns the integer square root of N\n[N] => [floor(sqrt(N))]\n\n[0] => [0], [1] => [1], [2] => [1], [3] => [1]\n[4] => [2], [8] => [2], [9] => [3], [99] => [9], [100] => [10]\n","desc":"returns the integer square root of N","effect":"[N] => [floor(sqrt(N))]","cases":[[[0],[0]],[[1],[1]],[[2],[1]],[[3],[1]],[[4],[2]],[[8],[2]],[[9],[3]],[[99],[9]],[[100],[10]]]},"ilog":{"full":"returns the intger logarithm of N in base B\n[N B] => [logB(N)]\n\n[15 4] => [1]\n[16 4] => [2]\n[100 10] => [2]\n[42 2] => [5]\n","desc":"returns the intger logarithm of N in base B","effect":"[N B] => [logB(N)]","cases":[[[15,4],[1]],[[16,4],[2]],[[100,10],[2]],[[42,2],[5]]]},"gcd":{"full":"returns the greatest common divisor of A and B\n[A B] => [gcd(A, B)]\n\n[6 9] => [3]\n[13 17] => [1]\n[24 36] => [12]\n","desc":"returns the greatest common divisor of A and B","effect":"[A B] => [gcd(A, B)]","cases":[[[6,9],[3]],[[13,17],[1]],[[24,36],[12]]]},"lcm":{"full":"returns the least common multiple of A and B\n[A B] => [lcm(A, B)]\n\n[6 9] => [18]\n[13 17] => [221]\n[24 36] => [72]\n","desc":"returns the least common multiple of A and B","effect":"[A B] => [lcm(A, B)]","cases":[[[6,9],[18]],[[13,17],[221]],[[24,36],[72]]]},"min":{"full":"keeps the minimum of the top two stack values\n[A B] => [A < B ? A : B]\n\n[3 1] => [1]\n[2 4] => [2]\n","desc":"keeps the minimum of the top two stack values","effect":"[A B] => [A < B ? A : B]","cases":[[[3,1],[1]],[[2,4],[2]]]},"max":{"full":"keeps the maximum of the top two stack values\n[A B] => [A > B ? A : B]\n\n[3 1] => [3]\n[2 4] => [4]\n","desc":"keeps the maximum of the top two stack values","effect":"[A B] => [A > B ? A : B]","cases":[[[3,1],[3]],[[2,4],[4]]]},"sign":{"full":"returns -1, 0, or 1 to indicate the sign of N\n[N] => [-1 | 0 | 1]\n\n[17] => [1]\n[-25] => [-1]\n[0] => [0]\n","desc":"returns -1, 0, or 1 to indicate the sign of N","effect":"[N] => [-1 | 0 | 1]","cases":[[[17],[1]],[[-25],[-1]],[[0],[0]]]},"abs":{"full":"returns the absolute value of N\n[N] => [N < 0 ? -N : N]\n\n[-5] => [5]\n[10] => [10]\n[0] => [0]\n","desc":"returns the absolute value of N","effect":"[N] => [N < 0 ? -N : N]","cases":[[[-5],[5]],[[10],[10]],[[0],[0]]]},"divmod":{"full":"pops A and B and pushes both their quotient and modulus\n[A B] => [A/B A%B]\n\n[17 5] => [3 2]\n[42 6] => [7 0]\n[ 1 5] => [0 1]\n","desc":"pops A and B and pushes both their quotient and modulus","effect":"[A B] => [A/B A%B]","cases":[[[17,5],[3,2]],[[42,6],[7,0]],[[1,5],[0,1]]]},"pos?":{"full":"returns whether N is greater than 0\n[N] => [N > 0]\n\n[5] => [1] [-3] => [0] [0] => [0]\n","desc":"returns whether N is greater than 0","effect":"[N] => [N > 0]","cases":[[[5],[1]],[[-3],[0]],[[0],[0]]]},"neg?":{"full":"returns whether N is less than 0\n[N] => [N < 0]\n\n[5] => [0] [-3] => [1] [0] => [0]\n","desc":"returns whether N is less than 0","effect":"[N] => [N < 0]","cases":[[[5],[0]],[[-3],[1]],[[0],[0]]]},"divisors":{"full":"returns a pseudo-array of the positive divisors of N; as an optimization,\nthey're not returned in ascending order, but rather in two \"halves\".\nThe alternative is unnecessarily invoking to_a and clobbering heap.\n[N] => [D1 ... Dn n]\n\n[10] => [1 2 10 5 4]\n[12] => [1 2 3 12 6 4 6]\n[25] => [1 5 25 3] ; no duplicate for perfect squares\n[60] => [1 2 3 4 5 6 60 30 20 15 12 10 12]\n","desc":"returns a pseudo-array of the positive divisors of N; as an optimization,\nthey're not returned in ascending order, but rather in two \"halves\".\nThe alternative is unnecessarily invoking to_a and clobbering heap.","effect":"[N] => [D1 ... Dn n]","cases":[[[10],[1,2,10,5,4]],[[12],[1,2,3,12,6,4,6]],[[25],[1,5,25,3]],[[60],[1,2,3,4,5,6,60,30,20,15,12,10,12]]]},"nCk":{"full":"returns the number of ways to choose K elements from a set of N\n[N K]\n\n[ 4 5] => [0]\n[ 7 7] => [1]\n[13 3] => [286]\n[16 4] => [1820]\n[50 3] => [19600]\n","desc":"returns the number of ways to choose K elements from a set of N","effect":"[N K]","cases":[[[4,5],[0]],[[7,7],[1]],[[13,3],[286]],[[16,4],[1820]],[[50,3],[19600]]]}},"stack":{"roll":{"full":"rolls the Ith element (counting from 0) to the top of the stack,\nshifting the elements above it down by 1.\n[I]\n\n[1 2 3 2] => [2 3 1]\n[1 2 3 4 1] => [1 2 4 3]\n[1 2 3 4 5 3] => [1 3 4 5 2]\n","desc":"rolls the Ith element (counting from 0) to the top of the stack,\nshifting the elements above it down by 1.","effect":"[I]","cases":[[[1,2,3,2],[2,3,1]],[[1,2,3,4,1],[1,2,4,3]],[[1,2,3,4,5,3],[1,3,4,5,2]]]},"bury":{"full":"\"buries\" X in the stack at index I, counting from 0\n[X I]\n\n[1 2 3 4 2] => [1 4 2 3] ; 2nd element of stack now 4\n[1 2 3 4 5 8 5] => [8 1 2 3 4 5]\n","desc":"\"buries\" X in the stack at index I, counting from 0","effect":"[X I]","cases":[[[1,2,3,4,2],[1,4,2,3]],[[1,2,3,4,5,8,5],[8,1,2,3,4,5]]]},"dig":{"full":"\"digs\" out the Ith element of the stack and discards it\n[I]\n\n[1 2 3 4 5 2] => [1 2 4 5]\n[1 2 3 4 5 4] => [2 3 4 5]\n","desc":"\"digs\" out the Ith element of the stack and discards it","effect":"[I]","cases":[[[1,2,3,4,5,2],[1,2,4,5]],[[1,2,3,4,5,4],[2,3,4,5]]]},"to_a":{"full":"pops elements off the stack until it hits the specified sentinel value S,\npushing them to the resulting pseudo-array. It's often more convenient to\nbuild up a collection in reverse order, and we often don't know in advance\nhow many elements we'll meet, but we do know to stop at the sentinel.\n[S En ... E1 S] => [E1 ... En n]\n\n[-1 9 8 7 -1] => [7 8 9 3]\n[0 'c' 'b' 'a' 0] => ['a' 'b' 'c' 3]\n","desc":"pops elements off the stack until it hits the specified sentinel value S,\npushing them to the resulting pseudo-array. It's often more convenient to\nbuild up a collection in reverse order, and we often don't know in advance\nhow many elements we'll meet, but we do know to stop at the sentinel.","effect":"[S En ... E1 S] => [E1 ... En n]","cases":[[[-1,9,8,7,-1],[7,8,9,3]],[[0,99,98,97,0],[97,98,99,3]]]},"npop":{"full":"pops N elements off the top of the stack\n[N]\n\n[1 2 3 4 5 3] => [1 2]\n[1 2 3 4 0] => [1 2 3 4]\n","desc":"pops N elements off the top of the stack","effect":"[N]","cases":[[[1,2,3,4,5,3],[1,2]],[[1,2,3,4,0],[1,2,3,4]]]},"nslide":{"full":"slides N elements off the stack, as if the `slide` operator took an argument\n[N]\n\n[1 2 3 4 5 2] => [1 2 5]\n[1 2 3 4 1] => [1 2 4]\n","desc":"slides N elements off the stack, as if the `slide` operator took an argument","effect":"[N]","cases":[[[1,2,3,4,5,2],[1,2,5]],[[1,2,3,4,1],[1,2,4]]]},"ncopy":{"full":"copies the Nth element to the top of the stack; this does exactly what\na `copy N` instruction would do, but we don't always know N in advance\n[N]\n\n[1 2 3 4 0] => [1 2 3 4 4] ; `copy 0` is just dup\n[1 2 3 4 3] => [1 2 3 4 1]\n","desc":"copies the Nth element to the top of the stack; this does exactly what\na `copy N` instruction would do, but we don't always know N in advance","effect":"[N]","cases":[[[1,2,3,4,0],[1,2,3,4,4]],[[1,2,3,4,3],[1,2,3,4,1]]]}},"rational":{"to_r":{"full":"encodes a numerator N and a denominator D as a rational number R with the\nfollowing structure: ((N × $RAT + D) << 1) + sign (0 for negative, else 1).\nThis representation is nice because, with care, it makes it so that we never\nhave to involve the heap (besides divmod) just to do fairly basic arithmetic.\n[N D] => [R]\n\n[22 7] => [R(22,7)]\n[4 8] => [R(4,8)] ; no implicit simplification TODO: make it configurable?\n[5 1] => [R(5,1)] ; no conversion to integer (duh)\n[-3 4] => [R(-3,4)]\n[3 -4] => [R(-3,4)] ; sign always held in the numerator\n[-1 -3] => [R(1,3)]\n","desc":"encodes a numerator N and a denominator D as a rational number R with the\nfollowing structure: ((N × $RAT + D) << 1) + sign (0 for negative, else 1).\nThis representation is nice because, with care, it makes it so that we never\nhave to involve the heap (besides divmod) just to do fairly basic arithmetic.","effect":"[N D] => [R]","cases":[[[22,7],[94489280527]],[[4,8],[17179869201]],[[5,1],[21474836483]],[[-3,4],[12884901896]],[[3,-4],[12884901896]],[[-1,-3],[4294967303]]]},"ratnum":{"full":"returns the numerator N of the rational number R, which may be negative\n[R] => [N]\n\n[R(22,7)] => [22]\n[R(-3,4)] => [-3]\n[R(3,-4)] => [-3]\n","desc":"returns the numerator N of the rational number R, which may be negative","effect":"[R] => [N]","cases":[[[94489280527],[22]],[[12884901896],[-3]],[[12884901896],[-3]]]},"ratden":{"full":"returns the denominator D of the rational number R; always positive\n[R] => [D]\n\n[R(22,7)] => [7]\n[R(-3,4)] => [4]\n[R(3,-4)] => [4]\n","desc":"returns the denominator D of the rational number R; always positive","effect":"[R] => [D]","cases":[[[94489280527],[7]],[[12884901896],[4]],[[12884901896],[4]]]},"from_r":{"full":"decomposes the rational number R into its numerator N and denominator D\n[R] => [N D]\n\n[R(22,7)] => [22 7]\n[R(-3,4)] => [-3 4]\n[R(3,-4)] => [-3 4]\n[R(4,8)] => [4 8] ; no implicit simplification\n","desc":"decomposes the rational number R into its numerator N and denominator D","effect":"[R] => [N D]","cases":[[[94489280527],[22,7]],[[12884901896],[-3,4]],[[12884901896],[-3,4]],[[17179869201],[4,8]]]},"ratsimp":{"full":"fully simplifies the rational number R by dividing both of its components\nby their greatest common divisor\n[R] => [R, simplified]\n\n[R(4,8)] => [R(1,2)]\n[R(-3,12)] => [R(-1,4)]\n[R(17,-51)] => [R(-1,3)]\n","desc":"fully simplifies the rational number R by dividing both of its components\nby their greatest common divisor","effect":"[R] => [R, simplified]","cases":[[[17179869201],[4294967301]],[[12884901912],[4294967304]],[[73014444134],[4294967302]]]},"ratadd":{"full":"returns the simplified sum of the rational numbers Ra and Rb\n[Ra Rb] => [Ra + Rb]\n\n[R(-9,-14) R(-3,19)] => [R(129,266)]\n[R(17,30) R(18,10)] => [R(71,30)]\n[R(-27,14) R(15,-23)] => [R(-831,322)]\n[R(3,-9) R(8,3)] => [R(7,3)]\n[R(-5,27) R(-2,-27)] => [R(-1,9)]\n[R(-27,-8) R(-15,22)] => [R(237,88)]\n[R(-9,-29) R(-27,3)] => [R(-252,29)]\n[R(2,-21) R(4,6)] => [R(4,7)]\n","desc":"returns the simplified sum of the rational numbers Ra and Rb","effect":"[Ra Rb] => [Ra + Rb]","cases":[[[38654705693,12884901926],[554050781717]],[[73014444093,77309411349],[304942678077]],[[115964117020,64424509486],[3569117823620]],[[12884901906,34359738375],[30064771079]],[[21474836534,8589934647],[4294967314]],[[115964117009,64424509484],[1017907249329]],[[38654705723,115964116998],[1082331758650]],[[8589934634,17179869197],[17179869199]]]},"ratsub":{"full":"returns the simplified difference of the rational numbers Ra and Rb\n[Ra Rb] => [Ra - Rb]\n\n[R(21,25) R(-28,27)] => [R(1267,675)]\n[R(14,7) R(13,6)] => [R(-1,6)]\n[R(-24,-9) R(-5,-21)] => [R(17,7)]\n[R(-27,-2) R(-2,26)] => [R(353,26)]\n[R(-27,3) R(2,-22)] => [R(-98,11)]\n[R(-4,23) R(-9,13)] => [R(155,299)]\n[R(-14,19) R(-18,-11)] => [R(-496,209)]\n[R(-29,21) R(-15,-16)] => [R(-779,336)]\n","desc":"returns the simplified difference of the rational numbers Ra and Rb","effect":"[Ra Rb] => [Ra - Rb]","cases":[[[90194313267,120259084342],[5441723565383]],[[60129542159,55834574861],[4294967308]],[[103079215123,21474836523],[73014444047]],[[115964116997,8589934644],[1516123455541]],[[115964116998,8589934636],[420906795030]],[[17179869230,38654705690],[665719931479]],[[60129542182,77309411351],[2130303779234]],[[124554051626,64424509473],[3345779524256]]]},"ratmul":{"full":"returns the simplified product of the rational numbers Ra and Rb\n[Ra Rb] => [Ra × Rb]\n\n[R(-24,26) R(-1,-30)] => [R(-2,65)]\n[R(19,4) R(27,2)] => [R(513,8)]\n[R(25,27) R(4,-11)] => [R(-100,297)]\n[R(1,18) R(4,8)] => [R(1,36)]\n[R(1,27) R(-8,29)] => [R(-8,783)]\n[R(25,-13) R(-6,24)] => [R(25,52)]\n[R(6,-13) R(9,23)] => [R(-54,299)]\n[R(11,8) R(-19,-19)] => [R(11,8)]\n","desc":"returns the simplified product of the rational numbers Ra and Rb","effect":"[Ra Rb] => [Ra × Rb]","cases":[[[103079215156,4294967357],[8589934722]],[[81604378633,115964116997],[2203318222865]],[[107374182455,17179869206],[429496730194]],[[4294967333,17179869201],[4294967369]],[[4294967351,34359738426],[34359739934]],[[107374182426,25769803824],[107374182505]],[[25769803802,38654705711],[231928234582]],[[47244640273,81604378663],[47244640273]]]},"ratdiv":{"full":"returns the simplified quotient of the rational numbers Ra and Rb\n[Ra Rb] => [Ra / Rb]\n\n[R(-30,-22) R(15,12)] => [R(12,11)]\n[R(13,28) R(-15,29)] => [R(-377,420)]\n[R(7,-30) R(-22,-12)] => [R(-7,55)]\n[R(15,4) R(8,-8)] => [R(-15,4)]\n[R(-23,28) R(-16,-15)] => [R(-345,448)]\n[R(-18,12) R(6,18)] => [R(-9,2)]\n[R(29,-2) R(11,-21)] => [R(609,22)]\n[R(-23,25) R(25,-3)] => [R(69,625)]\n","desc":"returns the simplified quotient of the rational numbers Ra and Rb","effect":"[Ra Rb] => [Ra / Rb]","cases":[[[128849018925,64424509465],[51539607575]],[[55834574905,64424509498],[1619202671432]],[[30064771132,94489280537],[30064771182]],[[64424509449,34359738384],[64424509448]],[[98784247864,68719476767],[1481763718016]],[[77309411352,25769803813],[38654705668]],[[124554051588,47244640298],[2615635083309]],[[98784247858,107374182406],[296352744675]]]},"ratmod":{"full":"returns the simplified modulus of the rational numbers Ra and Rb\n[Ra Rb] => [Ra % Rb]\n\n[R(-15,-3) R(-16,-10)] => [R(1,5)]\n[R(4,2) R(21,21)] => [R(0,1)]\n[R(24,10) R(-18,-3)] => [R(12,5)]\n[R(3,-7) R(-2,16)] => [R(-3,56)]\n[R(4,28) R(-29,7)] => [R(-4,1)]\n[R(7,-27) R(10,23)] => [R(109,621)]\n[R(28,-3) R(30,-12)] => [R(-11,6)]\n[R(-29,21) R(19,-23)] => [R(-268,483)]\n","desc":"returns the simplified modulus of the rational numbers Ra and Rb","effect":"[Ra Rb] => [Ra % Rb]","cases":[[[64424509447,68719476757],[4294967307]],[[17179869189,90194313259],[3]],[[103079215125,77309411335],[51539607563]],[[12884901902,8589934624],[12884902000]],[[17179869241,124554051598],[17179869186]],[[30064771126,42949673007],[468151436507]],[[120259084294,128849018904],[47244640268]],[[124554051626,81604378670],[1151051236294]]]},"ratsign":{"full":"returns the sign of the rational number R\n[R] => [-1 | 0 | 1]\n\n[R(4,3)] => [1]\n[R(4,-3)] => [-1]\n[R(0,10)] => [0]\n[R(-3,4)] => [-1]\n[R(-3,-4)] => [1]\n","desc":"returns the sign of the rational number R","effect":"[R] => [-1 | 0 | 1]","cases":[[[17179869191],[1]],[[17179869190],[-1]],[[21],[0]],[[12884901896],[-1]],[[12884901897],[1]]]},"ratinv":{"full":"returns the simplified inverse of the rational number R\n[R] => [1/R]\n\n[R(4,8)] => [R(2,1)]\n[R(3,-5)] => [R(-5,3)]\n[R(-22,-7)] => [R(7,22)]\n","desc":"returns the simplified inverse of the rational number R","effect":"[R] => [1/R]","cases":[[[17179869201],[8589934595]],[[12884901898],[21474836486]],[[94489280527],[30064771117]]]},"ratpow":{"full":"returns the rational R raised to the power E\n[R E] => [R']\n\n[R(4,2) 5] => [R(32,1)]\n[R(-3,7) 0] => [R(1,1)]\n[R(-3,14) 2] => [R(9,196)]\n","desc":"returns the rational R raised to the power E","effect":"[R E] => [R']","cases":[[[17179869189,5],[137438953475]],[[12884901902,0],[4294967299]],[[12884901916,2],[38654706057]]]}},"string":{"strpack":{"full":"convert a 0-terminated string on the stack to a single base-128 integer\n[0 ... c b a] => [\"abc...\"]\n\n[0 99 98 97] => [\"abc\"]\n[0 99 98 97] => [1634657]\n[0] => [0]\n","desc":"convert a 0-terminated string on the stack to a single base-128 integer","effect":"[0 ... c b a] => [\"abc...\"]","cases":[[[0,99,98,97],[1634657]],[[0,99,98,97],[1634657]],[[0],[0]]]},"strunpack":{"full":"convert a single base-128 integer to a 0-terminated string on the stack\n[\"abc...\"] => [0 ... c b a]\n\n[\"abc\"] => [0 99 98 97]\n[1634657] => [0 99 98 97]\n[0] => [0]\n","desc":"convert a single base-128 integer to a 0-terminated string on the stack","effect":"[\"abc...\"] => [0 ... c b a]","cases":[[[1634657],[0,99,98,97]],[[1634657],[0,99,98,97]],[[0],[0]]]},"strlen":{"full":"returns the length of a packed string, which is just the\nvalue itself log-128, +1 if the integer logarithm isn't exact.\n[S] => [len(S)]\n\n[\"\"] => [0]\n[\"abc\"] => [3]\n[\"foobar\"] => [6]\n","desc":"returns the length of a packed string, which is just the\nvalue itself log-128, +1 if the integer logarithm isn't exact.","effect":"[S] => [len(S)]","cases":[[[0],[0]],[[1634657],[3]],[[3943255767014],[6]]]},"strcat":{"full":"takes two packed strings and returns their concatenation (as a packed string)\n[S T] => [S+T]\n\n[\"foo\" \"\"] => [\"foo\"]\n[\"\" \"foo\"] => [\"foo\"]\n[\"foo\" \"bar\"] => [\"foobar\"]\n","desc":"takes two packed strings and returns their concatenation (as a packed string)","effect":"[S T] => [S+T]","cases":[[[1832934,0],[1832934]],[[0,1832934],[1832934]],[[1832934,1880290],[3943255767014]]]},"strrev":{"full":"reverses a packed string \"in-place\"\n[S] => [S']\n\n[\"foo\"] => [\"oof\"]\n[\"bark\"] => [\"krab\"]\n[\"ab\"] => [\"ba\"] ['a'] => ['a'] [\"\"] => [\"\"]\n","desc":"reverses a packed string \"in-place\"","effect":"[S] => [S']","cases":[[[1832934],[1685487]],[[226275554],[207124843]],[[12641],[12514]],[[97],[97]],[[0],[0]]]},"strslice":{"full":"takes a packed string S, a start index I, and a length L and returns the\ncorresponding substring (simply by doing division with powers of 128; neat)\n[S I L] => [S']\n\n[\"foobar\" 0 6] => [\"foobar\"]\n[\"foobar\" 1 4] => [\"ooba\"]\n[\"foobar\" 1 10] => [\"oobar\"]\n[\"foobar\" 5 1] => ['r']\n[\"foobar\" 6 0] => [\"\"]\n","desc":"takes a packed string S, a start index I, and a length L and returns the\ncorresponding substring (simply by doing division with powers of 128; neat)","effect":"[S I L] => [S']","cases":[[[3943255767014,0,6],[3943255767014]],[[3943255767014,1,4],[205043695]],[[3943255767014,1,10],[30806685679]],[[3943255767014,5,1],[114]],[[3943255767014,6,0],[0]]]},"strindex":{"full":"returns the index I of substring T in string S (or -1 if not found)\n[S T] => [I]\n\n[\"foobar\" 'o'] => [1]\n[\"foobar\" \"ob\"] => [2]\n[\"foobar\" \"\"] => [0]\n[\"foobar\" \"bar\"] => [3]\n[\"foobar\" \"bark\"] => [-1]\n","desc":"returns the index I of substring T in string S (or -1 if not found)","effect":"[S T] => [I]","cases":[[[3943255767014,111],[1]],[[3943255767014,12655],[2]],[[3943255767014,0],[0]],[[3943255767014,1880290],[3]],[[3943255767014,226275554],[-1]]]},"charat":{"full":"returns the character C at index I in string S\n[S I] => [C]\n\n[\"foobar\" 1] => ['o']\n[\"foobar\" 3] => ['b']\n[\"foobar\" 5] => ['r']\n[\"foobar\" 6] => [\"\"]\n","desc":"returns the character C at index I in string S","effect":"[S I] => [C]","cases":[[[3943255767014,1],[111]],[[3943255767014,3],[98]],[[3943255767014,5],[114]],[[3943255767014,6],[0]]]},"isalpha":{"full":"returns 1 if the character at the top of the stack is\nalphabetical (ASCII 65-90 or 97-122), 0 otherwise\n[C] => [0 | 1]\n\n['@'] => [0] ['a'] => [1]\n['z'] => [1] ['['] => [0]\n['`'] => [0] ['A'] => [1]\n['Z'] => [1] ['{'] => [0]\n","desc":"returns 1 if the character at the top of the stack is\nalphabetical (ASCII 65-90 or 97-122), 0 otherwise","effect":"[C] => [0 | 1]","cases":[[[64],[0]],[[97],[1]],[[122],[1]],[[91],[0]],[[96],[0]],[[65],[1]],[[90],[1]],[[123],[0]]]},"strrep":{"full":"returns string S replicated N times\n[S N] => [S']\n\n[\"abc\" 1] => [\"abc\"]\n[\"abc\" 2] => [\"abcabc\"]\n[\"abc\" 0] => [\"\"]\n","desc":"returns string S replicated N times","effect":"[S N] => [S']","cases":[[[1634657,1],[1634657]],[[1634657,2],[3428125831521]],[[1634657,0],[0]]]},"ljustc":{"full":"left-justifies string S to width W with character C\n[S W C] => [S']\n\n[\"foo\" 5 'x'] => [\"fooxx\"]\n[\"foobar\" 4 'x'] => [\"foobar\"]\n[\"\" 3 'x'] => [\"xxx\"]\n","desc":"left-justifies string S to width W with character C","effect":"[S W C] => [S']","cases":[[[1832934,5,120],[32465745894]],[[3943255767014,4,120],[3943255767014]],[[0,3,120],[1981560]]]},"ljust":{"full":"left-justifies string S to width W with spaces\n[S W] => [S']\n\n[\"foo\" 5] => [\"foo \"]\n[\"foobar\" 4] => [\"foobar\"]\n[\"\" 3] => [528416]\n","desc":"left-justifies string S to width W with spaces","effect":"[S W] => [S']","cases":[[[1832934,5],[8658876390]],[[3943255767014,4],[3943255767014]],[[0,3],[528416]]]},"rjustc":{"full":"right-justifies string S to width W with character C\n[S W C] => [S']\n\n[\"foo\" 5 'x'] => [\"xxfoo\"]\n[\"foobar\" 4 'x'] => [\"foobar\"]\n[\"\" 3 'x'] => [\"xxx\"]\n","desc":"right-justifies string S to width W with character C","effect":"[S W C] => [S']","cases":[[[1832934,5,120],[30030806136]],[[3943255767014,4,120],[3943255767014]],[[0,3,120],[1981560]]]},"rjust":{"full":"right-justifies string S to width W with spaces\n[S W C] => [S']\n\n[\"foo\" 5] => [\" foo\"]\n[\"foobar\" 4] => [\"foobar\"]\n[\"\" 3] => [528416]\n","desc":"right-justifies string S to width W with spaces","effect":"[S W C] => [S']","cases":[[[1832934,5],[30030794784]],[[3943255767014,4],[3943255767014]],[[0,3],[528416]]]},"centerc":{"full":"centers string S to width W with character C, favoring left alignment when\nthere's a parity mismatch (even-length string to odd width or vice versa)\n[S W C] => [S']\n\n[\"abc\" 7 'x'] => [\"xxabcxx\"]\n[\"abc\" 6 'x'] => [\"xabcxx\"]\n[\"abcd\" 6 'o'] => [\"oabcdo\"]\n[\"abcd\" 7 'o'] => [\"oabcdoo\"]\n[\"abcd\" 3 '!'] => [\"abcd\"]\n","desc":"centers string S to width W with character C, favoring left alignment when\nthere's a parity mismatch (even-length string to odd width or vice versa)","effect":"[S W C] => [S']","cases":[[[1634657,7,120],[531915532172408]],[[1634657,6,120],[4155590095096]],[[211349857,6,111],[3840983740655]],[[211349857,7,111],[492024146473199]],[[211349857,3,33],[211349857]]]},"center":{"full":"centers string S to width W with spaces\n[S W] => [S']\n\n[\"abc\" 7] => [\" abc \"]\n[\"abc\" 6] => [\" abc \"]\n[\"abcd\" 6] => [\" abcd \"]\n[\"abcd\" 7] => [\" abcd \"]\n[\"abcd\" 3] => [\"abcd\"]\n","desc":"centers string S to width W with spaces","effect":"[S W] => [S']","cases":[[[1634657,7],[141863782207520]],[[1634657,6],[1108310798496]],[[211349857,6],[1126564409504]],[[211349857,7],[141864052764832]],[[211349857,3],[211349857]]]},"strchop":{"full":"removes the last character of a string\n[S] => [S']\n\n[\"foobar\"] => [\"fooba\"]\n[\"abc\"] => [\"ab\"]\n[\"a\"] => [\"\"]\n","desc":"removes the last character of a string","effect":"[S] => [S']","cases":[[[3943255767014],[26245593062]],[[1634657],[12641]],[[97],[0]]]},"strsplit":{"full":"splits string S on delimiting character C, leaving the resultant substrings\non the stack as a pseudo-array (length at top of stack)\n[S C] => [A]\n\n[\"fooxbar\" 'x'] => [\"foo\" \"bar\" 2]\n[\"foobar\" 'x'] => [\"foobar\" 1]\n[\"foo|bar|baz\" '|'] => [\"foo\" \"bar\" \"baz\" 3]\n[\"foo,,bar\" ','] => [\"foo\" \"\" \"bar\" 3]\n[\"/foo/bar/\" '/'] => [\"\" \"foo\" \"bar\" \"\" 4]\n","desc":"splits string S on delimiting character C, leaving the resultant substrings\non the stack as a pseudo-array (length at top of stack)","effect":"[S C] => [A]","cases":[[[504736757053414,120],[1832934,1880290,2]],[[3943255767014,120],[3943255767014,1]],[[144933976769845798893542,124],[1832934,1880290,2011362,3]],[[64606284361234406,44],[1832934,0,1880290,3]],[[3451313205089661743,47],[0,1832934,1880290,0,4]]]},"lines":{"full":"splits the string S on newlines\n","desc":"","effect":"splits the string S on newlines","cases":[]},"strjoinc":{"full":"joins the pseudo-array of strings A into string S with delimiter string D\n[A D] => [S]\n\n[\"foo\" \"bar\" 2 'x'] => [\"fooxbar\"]\n[\"foo\" \"bar\" \"baz\" 3 '--'] => [\"foo--bar--baz\"]\n[\"foo\" 1 \"?!\"] => [\"foo\"]\n","desc":"joins the pseudo-array of strings A into string S with delimiter string D","effect":"[A D] => [S]","cases":[[[1832934,1880290,2,120],[504736757053414]],[[1832934,1880290,2011362,3,5805],[2374597541788353508880938982]],[[1832934,1,4287],[1832934]]]},"strjoin":{"full":"concatenates the pseudo-array of strings A into string S\n[A] => [S]\n\n[\"foo\" 1] => [\"foo\"]\n[\"foo\" \"bar\" 2] => [\"foobar\"]\n[\"foo\" 'x' \"bar\" 'x' \"baz\" 5] => [\"fooxbarxbaz\"]\n","desc":"concatenates the pseudo-array of strings A into string S","effect":"[A] => [S]","cases":[[[1832934,1],[1832934]],[[1832934,1880290,2],[3943255767014]],[[1832934,120,1880290,120,2011362,5],[144933974518045976819686]]]},"strcountc":{"full":"returns the number of ocurrences of character C in string S\n[S C] => [N]\n\n[\"foobar\" 'a'] => [1]\n[\"foobar\" 'o'] => [2]\n[\"foobar\" 'c'] => [0]\n","desc":"returns the number of ocurrences of character C in string S","effect":"[S C] => [N]","cases":[[[3943255767014,97],[1]],[[3943255767014,111],[2]],[[3943255767014,99],[0]]]},"strcount":{"full":"returns the total number of ocurrences of all characters in string T in string S\n[S T] => [N]\n\n[\"foobar\" 'o'] => [2]\n[\"foobar\" \"ob\"] => [3]\n[\"foxboar\" \"box\"] => [4]\n[\"eunoia\" \"aeiou\"] => [5]\n[\"why\" \"aeiou\"] => [0]\n","desc":"returns the total number of ocurrences of all characters in string T in string S","effect":"[S T] => [N]","cases":[[[3943255767014,111],[2]],[[3943255767014,12655],[3]],[[504740200724454,1980386],[4]],[[3361314945765,31641465569],[5]],[[1995895,31641465569],[0]]]},"strtrans":{"full":"translates all characters in A to the corresponding characters in B\nin stirng S, ; similar to the `tr` utility in Unix. A and B must be\nof the same length. TODO: make this smarter (ranges, length mismatch)\n[S A B] => [S']\n\n[\"abcd\" \"abc\" \"xyz\"] => [\"xyzd\"]\n[\"foobar\" \"oba\" \"ele\"] => [\"feeler\"]\n[\"abcdcba\" \"abcd\" \"xyz|\"] => [\"xyz|zyx\"]\n","desc":"translates all characters in A to the corresponding characters in B\nin stirng S, ; similar to the `tr` utility in Unix. A and B must be\nof the same length. TODO: make this smarter (ranges, length mismatch)","effect":"[S A B] => [S']","cases":[[[211349857,1634657,2014456],[211729656]],[[3943255767014,1601903,1668709],[3944350315238]],[[430004552397153,211349857,262061304],[531956120861944]]]},"strexpand":{"full":"expands the length-2 string S to contain the intervening ASCII characters\n[S] => [S']\n\n[\"CJ\"] => [\"CDEFGHIJ\"]\n[\"DA\"] => [\"DCBA\"]\n[\"af\"] => [\"abcdef\"]\n[\"09\"] => [\"0123456789\"]\n[\"90\"] => [\"9876543210\"]\n[\"(1\"] => [\"()*+,-./01\"]\n","desc":"expands the length-2 string S to contain the intervening ASCII characters","effect":"[S] => [S']","cases":[[[9539],[41981847056507459]],[[8388],[137404868]],[[13153],[3532016644449]],[[7344],[529798632943928514736]],[[6201],[446281053475978468409]],[[6312],[455430656835745125544]]]},"strsqueeze":{"full":"\"squeezes\" runs of the same character in string S to just one occurrence\n[S] => [S']\n\n[\"abc\"] => [\"abc\"]\n[\"foobar\"] => [\"fobar\"]\n[\"bookkeeper\"] => [\"bokeper\"]\n[\"xxxxxxx\"] => [\"x\"]\n","desc":"\"squeezes\" runs of the same character in string S to just one occurrence","effect":"[S] => [S']","cases":[[[1634657],[1634657]],[[3943255767014],[30806685670]],[[1058805727296038369250],[504877914191842]],[[531921215831160],[120]]]},"strsum":{"full":"returns the sum of the ordinal values of the characters in string S\n[S] => [N]\n\n[\"ABC\"] => [198]\n[\"012\"] => [147]\n[\"a\"] => [97]\n[\"\"] => [] TODO: bug, should be 0\n","desc":"returns the sum of the ordinal values of the characters in string S","effect":"[S] => [N]","cases":[[[1106241],[198]],[[825520],[147]],[[97],[97]],[[0],[]]]},"strrotl":{"full":"rotates the string S to the left N times, wrapping\n[S N]\n\n[\"abc\" 0] => [\"abc\"]\n[\"abcd\" 1] => [\"bcda\"]\n[\"abcd\" 5] => [\"bcda\"]\n[\"foodbar\" 4] => [\"barfood\"]\n","desc":"rotates the string S to the left N times, wrapping","effect":"[S N]","cases":[[[1634657,0],[1634657]],[[211349857,1],[205074914]],[[211349857,5],[205074914]],[[504736715110374,4],[443648594194658]]]},"strrotr":{"full":"rotates the string S to the right N times, wrapping\n[S N]\n\n[\"abcd\" 1] => [\"dabc\"]\n[\"abcd\" 5] => [\"dabc\"]\n[\"foodbar\" 3] => [\"barfood\"]\n","desc":"rotates the string S to the right N times, wrapping","effect":"[S N]","cases":[[[211349857,1],[209236196]],[[211349857,5],[209236196]],[[504736715110374,3],[443648594194658]]]}},"bits":{"band":{"full":"returns the bitwise AND of A and B\n[A B] => [A & B]\n\n[65 47] => [1] [83 25] => [17]\n[40 64] => [0] [74 59] => [10]\n[31 18] => [18] [86 32] => [0]\n[93 79] => [77] [11 79] => [11]\n","desc":"returns the bitwise AND of A and B","effect":"[A B] => [A & B]","cases":[[[65,47],[1]],[[83,25],[17]],[[40,64],[0]],[[74,59],[10]],[[31,18],[18]],[[86,32],[0]],[[93,79],[77]],[[11,79],[11]]]},"bor":{"full":"returns the bitwise OR of A and B\n[A B] => [A | B]\n\n[66 51] => [115] [64 4] => [68]\n[61 77] => [125] [93 65] => [93]\n[14 87] => [95] [71 37] => [103]\n[7 19] => [23] [38 92] => [126]\n","desc":"returns the bitwise OR of A and B","effect":"[A B] => [A | B]","cases":[[[66,51],[115]],[[64,4],[68]],[[61,77],[125]],[[93,65],[93]],[[14,87],[95]],[[71,37],[103]],[[7,19],[23]],[[38,92],[126]]]},"bxor":{"full":"returns the bitwise XOR of A and B\n[A B] => [A ^ B]\n\n[4 14] => [10] [0 80] => [80]\n[51 5] => [54] [97 77] => [44]\n[39 65] => [102] [12 26] => [22]\n[44 36] => [8] [6 21] => [19]\n","desc":"returns the bitwise XOR of A and B","effect":"[A B] => [A ^ B]","cases":[[[4,14],[10]],[[0,80],[80]],[[51,5],[54]],[[97,77],[44]],[[39,65],[102]],[[12,26],[22]],[[44,36],[8]],[[6,21],[19]]]},"bnot":{"full":"returns the infinite-precision bitwise NOT of N by inverting all of its bits\n[N] => [~N]\n\n[58] => [5] [46] => [17]\n[48] => [15] [87] => [40]\n[98] => [29] [51] => [12]\n[3] => [0] [42] => [21]\n","desc":"returns the infinite-precision bitwise NOT of N by inverting all of its bits","effect":"[N] => [~N]","cases":[[[58],[5]],[[46],[17]],[[48],[15]],[[87],[40]],[[98],[29]],[[51],[12]],[[3],[0]],[[42],[21]]]},"blength":{"full":"returns the number of bits in the binary representation of N\n[N] => [# of bits]\n\n[0] => [0] [1] => [1]\n[7] => [3] [8] => [4]\n[255] => [8]\n","desc":"returns the number of bits in the binary representation of N","effect":"[N] => [# of bits]","cases":[[[0],[0]],[[1],[1]],[[7],[3]],[[8],[4]],[[255],[8]]]},"popcount":{"full":"returns the number of set bits in N\n[N] => [popcount]\n\n[0] => [0] [1] => [1]\n[7] => [3] [8] => [1]\n","desc":"returns the number of set bits in N","effect":"[N] => [popcount]","cases":[[[0],[0]],[[1],[1]],[[7],[3]],[[8],[1]]]}},"io":{"print":{"full":"prints the character at the top of the stack until terminating zero\n","desc":"","effect":"prints the character at the top of the stack until terminating zero","cases":[]},"println":{"full":"print with newline\n","desc":"","effect":"print with newline","cases":[]},"getline":{"full":"reads a line of input onto the top of the stack as a packed string\n","desc":"","effect":"reads a line of input onto the top of the stack as a packed string","cases":[]},"readall":{"full":"consume stdin until EOF\n","desc":"","effect":"consume stdin until EOF","cases":[]}},"case":{"upcase":{"full":"returns string S with all alphabetical characters capitalized\n[S] => [S']\n\n[\"\"] => [\"\"]\n[\"abc\"] => [\"ABC\"]\n[\"123\"] => [\"123\"]\n[\"Abc123Def\"] => [\"ABC123DEF\"]\n","desc":"returns string S with all alphabetical characters capitalized","effect":"[S] => [S']","cases":[[[0],[0]],[[1634657],[1106241]],[[842033],[842033]],[[7407033370199781697],[5083175962476077377]]]},"downcase":{"full":"returns string S with all alphabetical characters lower-cased\n[S] => [S']\n\n[\"\"] => [\"\"]\n[\"ABC\"] => [\"abc\"]\n[\"123\"] => [\"123\"]\n[\"aBC123dEF\"] => [\"abc123def\"]\n","desc":"returns string S with all alphabetical characters lower-cased","effect":"[S] => [S']","cases":[[[0],[0]],[[1106241],[1634657]],[[842033],[842033]],[[5083316699964432737],[7407174107688137057]]]},"swapcase":{"full":"returns string S with the case of all alphabetical characters swapped\n[S] => [S']\n\n[\"\"] => [\"\"]\n[\"FooBar\"] => [\"fOObAR\"]\n[\"Abc123deF\"] => [\"aBC123DEf\"]\n","desc":"returns string S with the case of all alphabetical characters swapped","effect":"[S] => [S']","cases":[[[0],[0]],[[3943188658118],[2835153676262]],[[5101331098474443073],[7389018971689771361]]]}},"test":{},"array":{"arysum":{"full":"returns the sum of the array A\n[A] => [sum]\n\n[3 1] => [3]\n[4 3 2 1 4] => [10]\n[-10 -5 7 5 10 5] => [7]\n","desc":"returns the sum of the array A","effect":"[A] => [sum]","cases":[[[3,1],[3]],[[4,3,2,1,4],[10]],[[-10,-5,7,5,10,5],[7]]]},"arydup":{"full":"duplicates the array at the top of the stack\n[A] => [A A]\n\n[1 2 3 3] => [1 2 3 3 1 2 3 3]\n[7 50 10 2] => [7 50 10 2 50 10 2]\n","desc":"duplicates the array at the top of the stack","effect":"[A] => [A A]","cases":[[[1,2,3,3],[1,2,3,3,1,2,3,3]],[[7,50,10,2],[7,50,10,2,50,10,2]]]},"arypop":{"full":"removes the element at the end of the array A\n[A] => [A']\n\n[10 1] => [0]\n[1 2 3 4 4] => [1 2 3 3]\n[7 10 20 30 3] => [7 10 20 2]\n","desc":"removes the element at the end of the array A","effect":"[A] => [A']","cases":[[[10,1],[0]],[[1,2,3,4,4],[1,2,3,3]],[[7,10,20,30,3],[7,10,20,2]]]},"aryshift":{"full":"removes the element at the beginning of the array A\n[A] => [A']\n\n[10 1] => [0]\n[1 2 3 4 4] => [2 3 4 3]\n[7 10 20 30 3] => [7 20 30 2]\n","desc":"removes the element at the beginning of the array A","effect":"[A] => [A']","cases":[[[10,1],[0]],[[1,2,3,4,4],[2,3,4,3]],[[7,10,20,30,3],[7,20,30,2]]]},"arycat":{"full":"returns the concatenation of arrays A and B\n[A B] => [A+B]\n\n[1 2 3 3 4 5 6 3] => [1 2 3 4 5 6 6]\n[7 10 2 5 4 3 3] => [7 10 5 4 3 5]\n","desc":"returns the concatenation of arrays A and B","effect":"[A B] => [A+B]","cases":[[[1,2,3,3,4,5,6,3],[1,2,3,4,5,6,6]],[[7,10,2,5,4,3,3],[7,10,5,4,3,5]]]},"aryindex":{"full":"returns the index I of element E in array A (or -1 if not found)\n[A E] => [I]\n\n[1 2 3 4 4 2] => [1]\n[1 2 3 4 4 4] => [3]\n[1 2 3 4 4 5] => [-1]\n","desc":"returns the index I of element E in array A (or -1 if not found)","effect":"[A E] => [I]","cases":[[[1,2,3,4,4,2],[1]],[[1,2,3,4,4,4],[3]],[[1,2,3,4,4,5],[-1]]]},"aryat":{"full":"returns the element E at index I in array A (or dies on out of bounds)\n[A I] => [E]\n\n[1 2 3 4 4 0] => [1]\n[1 2 3 4 4 2] => [3]\n[1 2 3 4 4 -1] => [4] negative index counts from the end\n","desc":"returns the element E at index I in array A (or dies on out of bounds)","effect":"[A I] => [E]","cases":[[[1,2,3,4,4,0],[1]],[[1,2,3,4,4,2],[3]],[[1,2,3,4,4,-1],[4]]]},"minmax":{"full":"returns the minimum and maximum elements of array A\n[A] => [min max]\n\n[4 3 2 1 4] => [1 4]\n[6 8 -3 4 0 5] => [-3 8]\n[7 1] => [7 7]\n","desc":"returns the minimum and maximum elements of array A","effect":"[A] => [min max]","cases":[[[4,3,2,1,4],[1,4]],[[6,8,-3,4,0,5],[-3,8]],[[7,1],[7,7]]]},"aryrev":{"full":"reverses the array A\n[A] => [A']\n\n[1 2 3 3] => [3 2 1 3]\n[7 1] => [7 1]\n[5 4 3 2 1 5] => [1 2 3 4 5 5]\n","desc":"reverses the array A","effect":"[A] => [A']","cases":[[[1,2,3,3],[3,2,1,3]],[[7,1],[7,1]],[[5,4,3,2,1,5],[1,2,3,4,5,5]]]},"aryrep":{"full":"returns the array A replicated N times\n[A N] => [A']\n\n[3 2 1 3 4] => [3 2 1 3 2 1 3 2 1 3 2 1 12]\n","desc":"returns the array A replicated N times","effect":"[A N] => [A']","cases":[[[3,2,1,3,4],[3,2,1,3,2,1,3,2,1,3,2,1,12]]]}},"syntax":{},"util":{"range":{"full":"inserts between the top two stack values the intervening consecutive elements\nsupports counting up or down\n[I J] => [I I±1 ... J]\n\n[2 5] => [2 3 4 5]\n[5 2] => [5 4 3 2]\n[0 4] => [0 1 2 3 4]\n[4 0] => [4 3 2 1 0]\n[-2 0] => [-2 -1 0]\n[0 -2] => [0 -1 -2]\n[-3 3] => [-3 -2 -1 0 1 2 3]\n[3 -3] => [3 2 1 0 -1 -2 -3]\n[4 4] => [4 5] TODO: bug\n","desc":"inserts between the top two stack values the intervening consecutive elements\nsupports counting up or down","effect":"[I J] => [I I±1 ... J]","cases":[[[2,5],[2,3,4,5]],[[5,2],[5,4,3,2]],[[0,4],[0,1,2,3,4]],[[4,0],[4,3,2,1,0]],[[-2,0],[-2,-1,0]],[[0,-2],[0,-1,-2]],[[-3,3],[-3,-2,-1,0,1,2,3]],[[3,-3],[3,2,1,0,-1,-2,-3]],[[4,4],[4,5]]]},"steprange":{"full":"inserts between the top two stack values the intervening consecutive elements,\ncounting by `step` up/down to (but never beyond) J\n[I J S] => [I I±S ... ~J]\n\n[1 4 1] => [1 2 3 4]\n[4 1 -1] => [4 3 2 1]\n[2 10 3] => [2 5 8]\n[10 2 -3] => [10 7 4]\n[-5 25 10] => [-5 5 15 25]\n[25 -5 -10] => [25 15 5 -5]\n","desc":"inserts between the top two stack values the intervening consecutive elements,\ncounting by `step` up/down to (but never beyond) J","effect":"[I J S] => [I I±S ... ~J]","cases":[[[1,4,1],[1,2,3,4]],[[4,1,-1],[4,3,2,1]],[[2,10,3],[2,5,8]],[[10,2,-3],[10,7,4]],[[-5,25,10],[-5,5,15,25]],[[25,-5,-10],[25,15,5,-5]]]},"die!":{"full":"prints the string at the top of the stack and halts execution\n","desc":"","effect":"prints the string at the top of the stack and halts execution","cases":[]},"alpha":{"full":"for stoi and itos\n","desc":"","effect":"for stoi and itos","cases":[]},"stoi":{"full":"converts the string S to an integer in base B (2-36)\n[S B]\n\n[\"101010\" 2] => [42]\n[\"0777\" 8] => [511]\n[\"12345\" 10] => [12345]\n[\"123_\" 10] => [123]\n[\"123____\" 10] => [123000] ; TODO: bug\n[\"dead\" 16] => [57005]\n[\"gabe\" 17] => [81699]\n[\"0\" 10] => [0] [\"-0\" 10] => [0]\n[\"-10001\" 2] => [-17]\n[\"-123\" 10] => [-123]\n[\"-ff\" 16] => [-255]\n","desc":"converts the string S to an integer in base B (2-36)","effect":"[S B]","cases":[[[1662522251313,2],[42]],[[116251568,8],[511]],[[14336973105,10],[12345]],[[200071473,10],[123]],[[421104295139633,10],[123000]],[[211317476,16],[57005]],[[213430503,17],[81699]],[[48,10],[0]],[[6189,10],[0]],[[1696613537965,2],[-17]],[[107780269,10],[-123]],[[1684269,16],[-255]]]},"bin":{"full":"creature comforts\n","desc":"","effect":"creature comforts","cases":[]},"itos":{"full":"converts the integer N to a string in base B\n[N B]\n\n[42 2] => [\"101010\"]\n[511 8] => [\"777\"]\n[12345 10] => [\"12345\"]\n[57005 16] => [\"dead\"]\n[81699 17] => [\"gabe\"]\n","desc":"converts the integer N to a string in base B","effect":"[N B]","cases":[[[42,2],[1662522251313]],[[511,8],[908215]],[[12345,10],[14336973105]],[[57005,16],[211317476]],[[81699,17],[213430503]]]},"to_bin":{"full":"creature comforts\n","desc":"","effect":"creature comforts","cases":[]},"digits":{"full":"puts the digits of N in base B on the stack as a pseudo-array\n[N B] => [Dn ...D0 n]\n\n[42 2] => [1 0 1 0 1 0 6]\n[12345 10] => [1 2 3 4 5 5]\n[255 16] => [15 15 2]\n[256 16] => [1 0 0 3]\n","desc":"puts the digits of N in base B on the stack as a pseudo-array","effect":"[N B] => [Dn ...D0 n]","cases":[[[42,2],[1,0,1,0,1,0,6]],[[12345,10],[1,2,3,4,5,5]],[[255,16],[15,15,2]],[[256,16],[1,0,0,3]]]},"inc":{"full":"increments the value at heap address N TODO: make heap effects test-able ?\n[N]\n","desc":"increments the value at heap address N TODO: make heap effects test-able ?","effect":"[N]","cases":[]},"dec":{"full":"decrements the value at heap address N\n[N]\n","desc":"decrements the value at heap address N","effect":"[N]","cases":[]},"eq":{"full":"pops A and B and pushes 1 if they're equal, 0 otherwise\n[A B] => [A == B]\n\n[1 2] => [0]\n[3 3] => [1]\n[-4 4] => [0]\n['A' 65] => [1]\n['B' 65] => [0]\n","desc":"pops A and B and pushes 1 if they're equal, 0 otherwise","effect":"[A B] => [A == B]","cases":[[[1,2],[0]],[[3,3],[1]],[[-4,4],[0]],[[65,65],[1]],[[66,65],[0]]]},"neq":{"full":"pops A and B and pushes 1 if they're not equal, 0 otherwise\n[A B] => [A != B]\n\n[1 2] => [1]\n[3 3] => [0]\n[-4 4] => [1]\n['A' 65] => [0]\n['B' 65] => [1]\n","desc":"pops A and B and pushes 1 if they're not equal, 0 otherwise","effect":"[A B] => [A != B]","cases":[[[1,2],[1]],[[3,3],[0]],[[-4,4],[1]],[[65,65],[0]],[[66,65],[1]]]},"gt":{"full":"pops A and B and pushes 1 if A is greater than B, 0 otherwise\n[A B] => [A > B]\n\n[4 3] => [1] [3 4] => [0]\n[2 2] => [0] [2 1] => [1]\n","desc":"pops A and B and pushes 1 if A is greater than B, 0 otherwise","effect":"[A B] => [A > B]","cases":[[[4,3],[1]],[[3,4],[0]],[[2,2],[0]],[[2,1],[1]]]},"lt":{"full":"pops A and B and pushes 1 if A is less than than B, 0 otherwise\n[A B] => [A < B]\n\n[3 4] => [1] [4 3] => [0]\n[2 2] => [0] [1 2] => [1]\n","desc":"pops A and B and pushes 1 if A is less than than B, 0 otherwise","effect":"[A B] => [A < B]","cases":[[[3,4],[1]],[[4,3],[0]],[[2,2],[0]],[[1,2],[1]]]},"lte":{"full":"pops A and B and pushes 1 if A is less than or equal to B, 0 otherwise\n[A B] => [A > B]\n\n[2 2] => [1] [2 1] => [0]\n[4 3] => [0] [3 4] => [1]\n","desc":"pops A and B and pushes 1 if A is less than or equal to B, 0 otherwise","effect":"[A B] => [A > B]","cases":[[[2,2],[1]],[[2,1],[0]],[[4,3],[0]],[[3,4],[1]]]},"gte":{"full":"pops A and B and pushes 1 if A is greater than or equal to B, 0 otherwise\n[A B] => [A > B]\n\n[2 2] => [1] [1 2] => [0]\n[3 4] => [0] [4 3] => [1]\n","desc":"pops A and B and pushes 1 if A is greater than or equal to B, 0 otherwise","effect":"[A B] => [A > B]","cases":[[[2,2],[1]],[[1,2],[0]],[[3,4],[0]],[[4,3],[1]]]},"heap_seeking_missile":{"full":"Though extremely rare, it's possible that we know a particular value is\nstored in the heap at some key, just not which one. This subroutine takes\na value V to search for and a starting index I, and either returns the first\nkey associated with that value or loops forever. Probably don't touch.\n[V I]\n","desc":"Though extremely rare, it's possible that we know a particular value is\nstored in the heap at some key, just not which one. This subroutine takes\na value V to search for and a starting index I, and either returns the first\nkey associated with that value or loops forever. Probably don't touch.","effect":"[V I]","cases":[]}},"prime":{"prime?":{"full":"returns 1 if the number N is prime, 0 otherwise\n[N] => [0 | 1]\n\n[0] => [0] [1] => [0]\n[2] => [1] [4] => [0]\n[3] => [1] [9] => [0]\n","desc":"returns 1 if the number N is prime, 0 otherwise","effect":"[N] => [0 | 1]","cases":[[[0],[0]],[[1],[0]],[[2],[1]],[[4],[0]],[[3],[1]],[[9],[0]]]},"next_prime":{"full":"returns the first prime number P greater than N\n[N] => [P]\n\n[0] => [2] [1] => [2]\n[2] => [3] [3] => [5]\n[13] => [17]\n[100] => [101]\n","desc":"returns the first prime number P greater than N","effect":"[N] => [P]","cases":[[[0],[2]],[[1],[2]],[[2],[3]],[[3],[5]],[[13],[17]],[[100],[101]]]},"factor":{"full":"returns the prime factorization of N as a pseudo-array\n[N] => [A]\n\n[2] => [2 1]\n[8] => [2 2 2 3]\n[15] => [3 5 2]\n[17] => [17 1]\n[100] => [2 2 5 5 4]\n","desc":"returns the prime factorization of N as a pseudo-array","effect":"[N] => [A]","cases":[[[2],[2,1]],[[8],[2,2,2,3]],[[15],[3,5,2]],[[17],[17,1]],[[100],[2,2,5,5,4]]]}}}
@@ -4,43 +4,55 @@ import stack ; to_a
4
4
  import string ; isalpha, strcat, strjoin, strrev, strunpack
5
5
  import util ; eq
6
6
 
7
+ ; returns whether the string S is the same forwards and backwards
8
+ ; [S] => [0 | 1]
9
+ ;
10
+ ; ["racecar"] => [1]
11
+ ; ["divider"] => [0]
12
+ ; ["redivider"] => [1]
7
13
  palindrome?: dup :strrev :eq ret
8
14
 
9
- ;;;
10
-
15
+ ; returns whether the strings S and T are composed of the same characters
16
+ ; [S T] => [0 | 1]
17
+ ;
18
+ ; ["allergy" "gallery"] => [1]
19
+ ; ["largely" "regally"] => [1]
20
+ ; ["foo" "bar"] => [0]
11
21
  anagrams?:
12
22
  :strunpack push 0 :to_a :sort :strjoin swap
13
23
  :strunpack push 0 :to_a :sort :strjoin :eq ret
14
24
 
15
- ;;;
16
-
17
- isop: :upcase push 0 swap ; tally
18
- _isop_loop: ; [t s]
19
- dup jz _isop_done
25
+ ; returns the sum of the alphabetical characters in string S where A=1, B=2...
26
+ ; [S] => [sum]
27
+ ;
28
+ ; ["Math"] => [42]
29
+ ; ["wizards"] => [100]
30
+ ; ["AbCd"] => [10]
31
+ isop: :upcase push 0 swap
32
+ _isop_loop: dup jz _isop_done
20
33
  swap copy 1 push 128 mod
21
- dup :isalpha jz _isop_no ; ignore non-alphabetical
22
- push 64
23
- _isop_resume:
24
- sub add
25
- swap push 128 div jump _isop_loop
26
-
34
+ dup :isalpha jz _isop_no push 64
35
+ _isop_resume: sub add swap push 128 div jump _isop_loop
27
36
  _isop_no: dup jump _isop_resume
28
-
29
37
  _isop_done: pop ret
30
38
 
31
- ;;;
32
-
39
+ ; returns the elements of the Collatz sequence for integer N as a pseudo-array
40
+ ; ! may run forever on some as-yet-unknown input
41
+ ; [N] => [A]
42
+ ;
43
+ ; [1] => [1 1]
44
+ ; [2] => [2 1 2]
45
+ ; [3] => [3 10 5 16 8 4 2 1 8]
46
+ ; [4] => [4 2 1 3]
47
+ ; [5] => [5 16 8 4 2 1 6]
33
48
  collatz: push 1 ; sequence length
34
49
  _collatz_loop:
35
50
  copy 1 dup push 1 sub jz _collatz_done
36
- dup push 2 mod ; m2 n m2
51
+ dup push 2 mod
37
52
  swap copy 1 push 2 mul $++ mul
38
53
  push 2 copy 2 sub div add
39
54
  swap $++ jump _collatz_loop
40
-
41
55
  _collatz_done: pop ret
42
56
 
43
- ;;;
44
-
45
- ruby:
46
- push "'" :strcat push "ruby -e 'p " swap :strcat shell ret
57
+ ; ruby:
58
+ ; push "'" :strcat push "ruby -e 'p " swap :strcat shell ret
@@ -2,10 +2,12 @@ import array ; arycat, arydup
2
2
  import util ; eq, inc, range
3
3
 
4
4
  ; returns B raised to the power E
5
+ ; ! TODO: support negative exponents (return Rational)
5
6
  ; [B E] => [B**E]
6
7
  ;
7
8
  ; [0 0] => [1], [0 9] => [0], [9 0] => [1]
8
9
  ; [3 2] => [9], [2 3] => [8], [7 4] => [2401]
10
+ ; [-2 3] => [-8] [-5 0] => [1] [-4 4] => [256]
9
11
  pow: push 1 swap
10
12
  _pow_loop: ; [b n e]
11
13
  dup jz _pow_done
@@ -18,10 +20,10 @@ _pow_done: swap slide 2 ret
18
20
  ;
19
21
  ; [0] => [1], [1] => [1], [2] => [2]
20
22
  ; [3] => [6], [5] => [120], [10] => [3628800]
21
- factorial: push 0 swap :range
23
+ factorial: dup jz _fac_zero push 0 swap :range
22
24
  _fac_loop: swap dup jz _fac_done mul jump _fac_loop
23
-
24
25
  _fac_done: pop ret
26
+ _fac_zero: $++ ret
25
27
 
26
28
  ; returns the integer square root of N
27
29
  ; [N] => [floor(sqrt(N))]
@@ -130,7 +132,7 @@ neg?: :sign push -1 :eq ret
130
132
  ; returns a pseudo-array of the positive divisors of N; as an optimization,
131
133
  ; they're not returned in ascending order, but rather in two "halves".
132
134
  ; The alternative is unnecessarily invoking to_a and clobbering heap.
133
- ; [N]
135
+ ; [N] => [D1 ... Dn n]
134
136
  ;
135
137
  ; [10] => [1 2 10 5 4]
136
138
  ; [12] => [1 2 3 12 6 4 6]
@@ -153,6 +155,8 @@ _divisors_square: slide 1 $-- ret ; de-duplicate when N is a perfect square
153
155
  ; [16 4] => [1820]
154
156
  ; [50 3] => [19600]
155
157
  nCk:
158
+ copy 1 copy 1 sub jn _nCk_empty
156
159
  copy 1 copy 1 sub :factorial
157
160
  swap :factorial mul
158
161
  swap :factorial swap div ret
162
+ _nCk_empty: push 0 slide 2 ret
@@ -1,45 +1,45 @@
1
1
  import math ; divmod
2
2
  import util ; inc
3
3
 
4
- ; [n] => [0|1]
5
- prime?: ; [n]
4
+ ; returns 1 if the number N is prime, 0 otherwise
5
+ ; [N] => [0 | 1]
6
+ ;
7
+ ; [0] => [0] [1] => [0]
8
+ ; [2] => [1] [4] => [0]
9
+ ; [3] => [1] [9] => [0]
10
+ prime?:
6
11
  dup push 3 sub jn _prime_special ; special-case < 3
7
12
  dup push 2 mod jz _prime_even ; otherwise, even -> false
8
- push 3
9
-
10
- _prime_loop: ; [n d]
11
- copy 1 copy 1 dup mul sub jn _prime_yes ; divisor > isqrt(n), n is prime
13
+ push 3 ; initial divisor to check
14
+ _prime_loop:
15
+ copy 1 copy 1 dup mul sub jn _prime_yes ; divisor > isqrt(n), so n is prime
12
16
  copy 1 copy 1 mod jz _prime_no
13
17
  push 2 add jump _prime_loop
14
-
15
- _prime_yes:
16
- pop dup div ret ; return 1
17
-
18
- _prime_even:
19
- push 1
20
- _prime_no:
21
- pop dup sub ret ; return 0
22
-
23
- _prime_special: ; [n]
24
- push 2 sub jz _prime_two
25
- push 0 ret ; false for n < 2
26
-
27
- _prime_two:
28
- push 1 ret
29
-
30
- ;;;
31
-
18
+ _prime_even: dup sub ret
19
+ _prime_no: pop dup sub ret ; return 0
20
+ _prime_yes: pop dup div ret ; return 1
21
+ _prime_special: push 2 :eq ret
22
+
23
+ ; returns the first prime number P greater than N
24
+ ; [N] => [P]
25
+ ;
26
+ ; [0] => [2] [1] => [2]
27
+ ; [2] => [3] [3] => [5]
28
+ ; [13] => [17]
29
+ ; [100] => [101]
32
30
  next_prime: push 1 add dup :prime? jz next_prime ret
33
31
 
34
- ;;;
35
-
36
- ; prime factorization
37
- factor: ; [n]
38
- push 2 swap ; initial divisor
39
- push -2,0 store ; number of prime factors
40
- _factor_loop: ; [d n]
41
- dup push 2 sub jn _factor_done
42
- jump _divisor_loop ; prevent dead code elimination :(
32
+ ; returns the prime factorization of N as a pseudo-array
33
+ ; ! N must be greater than 1
34
+ ; [N] => [A]
35
+ ;
36
+ ; [2] => [2 1]
37
+ ; [8] => [2 2 2 3]
38
+ ; [15] => [3 5 2]
39
+ ; [17] => [17 1]
40
+ ; [100] => [2 2 5 5 4]
41
+ factor: push 2 swap push -2,0 store
42
+ _factor_loop: dup push 2 sub jn _factor_done jump _divisor_loop
43
43
  _divisor_loop:
44
44
  dup copy 2 :divmod jz _divisor_keep
45
45
  pop swap :next_prime swap jump _factor_loop
@@ -151,3 +151,26 @@ ratsign:
151
151
  dup $RAT push 2 mul push 2 add sub jn _ratsign_zero
152
152
  push 2 mod push 2 mul push 1 sub ret
153
153
  _ratsign_zero: pop push 0 ret
154
+
155
+ ; returns the simplified inverse of the rational number R
156
+ ; [R] => [1/R]
157
+ ;
158
+ ; [R(4,8)] => [R(2,1)]
159
+ ; [R(3,-5)] => [R(-5,3)]
160
+ ; [R(-22,-7)] => [R(7,22)]
161
+ ratinv:
162
+ push 2 :divmod push 2 mul $--
163
+ swap $RAT :divmod copy 2 mul
164
+ swap :to_r :ratsimp slide 1 ret
165
+
166
+ ; returns the rational R raised to the power E
167
+ ; [R E] => [R']
168
+ ;
169
+ ; [R(4,2) 5] => [R(32,1)]
170
+ ; [R(-3,7) 0] => [R(1,1)]
171
+ ; [R(-3,14) 2] => [R(9,196)]
172
+ ratpow:
173
+ swap push 2 :divmod push 2 mul $--
174
+ swap $RAT :divmod copy 2 mul
175
+ copy 3 :pow swap copy 3 :pow
176
+ swap :to_r :ratsimp slide 2 ret
@@ -49,7 +49,7 @@ strlen: dup push 128 :ilog swap push 128 mod push 0 :neq add ret
49
49
  strcat: push 128 copy 2 :strlen :pow mul add ret
50
50
 
51
51
  ; reverses a packed string "in-place"
52
- ; [S] => [reverse(S)]
52
+ ; [S] => [S']
53
53
  ;
54
54
  ; ["foo"] => ["oof"]
55
55
  ; ["bark"] => ["krab"]
@@ -65,7 +65,7 @@ _strrev_done: pop ret
65
65
 
66
66
  ; takes a packed string S, a start index I, and a length L and returns the
67
67
  ; corresponding substring (simply by doing division with powers of 128; neat)
68
- ; [S I L] => [substring]
68
+ ; [S I L] => [S']
69
69
  ;
70
70
  ; ["foobar" 0 6] => ["foobar"]
71
71
  ; ["foobar" 1 4] => ["ooba"]
@@ -78,8 +78,8 @@ strslice:
78
78
  swap push 128 swap :pow
79
79
  mod slide 1 ret
80
80
 
81
- ; returns the index of substring T in string S (or -1 if not found)
82
- ; [S T] => [index]
81
+ ; returns the index I of substring T in string S (or -1 if not found)
82
+ ; [S T] => [I]
83
83
  ;
84
84
  ; ["foobar" 'o'] => [1]
85
85
  ; ["foobar" "ob"] => [2]
@@ -95,8 +95,8 @@ _strindex_loop: ; [t s i]
95
95
  _strindex_no: push -1 slide 3 ret
96
96
  _strindex_found: slide 2 ret
97
97
 
98
- ; returns the character at index I in string S
99
- ; [S I] => [char]
98
+ ; returns the character C at index I in string S
99
+ ; [S I] => [C]
100
100
  ;
101
101
  ; ["foobar" 1] => ['o']
102
102
  ; ["foobar" 3] => ['b']
@@ -106,7 +106,7 @@ charat: push 1 :strslice ret
106
106
 
107
107
  ; returns 1 if the character at the top of the stack is
108
108
  ; alphabetical (ASCII 65-90 or 97-122), 0 otherwise
109
- ; [C] => [0/1]
109
+ ; [C] => [0 | 1]
110
110
  ;
111
111
  ; ['@'] => [0] ['a'] => [1]
112
112
  ; ['z'] => [1] ['['] => [0]
@@ -119,7 +119,7 @@ isalpha:
119
119
  _isalpha_no: dup sub ret
120
120
 
121
121
  ; returns string S replicated N times
122
- ; [S N] => [S+S+...]
122
+ ; [S N] => [S']
123
123
  ;
124
124
  ; ["abc" 1] => ["abc"]
125
125
  ; ["abc" 2] => ["abcabc"]
@@ -138,7 +138,7 @@ _strrep_done: swap slide 2 ret
138
138
  _justc: swap copy 2 :strlen sub push 0 :max :strrep ret
139
139
 
140
140
  ; left-justifies string S to width W with character C
141
- ; [S W C] => [S, left-justified]
141
+ ; [S W C] => [S']
142
142
  ;
143
143
  ; ["foo" 5 'x'] => ["fooxx"]
144
144
  ; ["foobar" 4 'x'] => ["foobar"]
@@ -146,7 +146,7 @@ _justc: swap copy 2 :strlen sub push 0 :max :strrep ret
146
146
  ljustc: :_justc :strcat ret
147
147
 
148
148
  ; left-justifies string S to width W with spaces
149
- ; [S W] => [S, left-justified]
149
+ ; [S W] => [S']
150
150
  ;
151
151
  ; ["foo" 5] => ["foo "]
152
152
  ; ["foobar" 4] => ["foobar"]
@@ -154,7 +154,7 @@ ljustc: :_justc :strcat ret
154
154
  ljust: push ' ' :ljustc ret
155
155
 
156
156
  ; right-justifies string S to width W with character C
157
- ; [S W C] => [S, right-justified]
157
+ ; [S W C] => [S']
158
158
  ;
159
159
  ; ["foo" 5 'x'] => ["xxfoo"]
160
160
  ; ["foobar" 4 'x'] => ["foobar"]
@@ -162,7 +162,7 @@ ljust: push ' ' :ljustc ret
162
162
  rjustc: :_justc swap :strcat ret
163
163
 
164
164
  ; right-justifies string S to width W with spaces
165
- ; [S W C] => [S, right-justified]
165
+ ; [S W C] => [S']
166
166
  ;
167
167
  ; ["foo" 5] => [" foo"]
168
168
  ; ["foobar" 4] => ["foobar"]
@@ -172,7 +172,7 @@ rjust: push ' ' :rjustc ret
172
172
  ; centers string S to width W with character C, favoring left alignment when
173
173
  ; there's a parity mismatch (even-length string to odd width or vice versa)
174
174
  ; ! TODO: This seems unnecessarily intricate, but perhaps just its nature.
175
- ; [S W C] => [S, centered]
175
+ ; [S W C] => [S']
176
176
  ;
177
177
  ; ["abc" 7 'x'] => ["xxabcxx"]
178
178
  ; ["abc" 6 'x'] => ["xabcxx"]
@@ -190,7 +190,7 @@ centerc:
190
190
  slide 2 ret
191
191
 
192
192
  ; centers string S to width W with spaces
193
- ; [S W] => [S, centered]
193
+ ; [S W] => [S']
194
194
  ;
195
195
  ; ["abc" 7] => [" abc "]
196
196
  ; ["abc" 6] => [" abc "]
@@ -202,7 +202,7 @@ center: push ' ' :centerc ret
202
202
  ;;;
203
203
 
204
204
  ; removes the last character of a string
205
- ; [S] => [S.chop]
205
+ ; [S] => [S']
206
206
  ;
207
207
  ; ["foobar"] => ["fooba"]
208
208
  ; ["abc"] => ["ab"]
@@ -296,7 +296,7 @@ strcount:
296
296
  ; in stirng S, ; similar to the `tr` utility in Unix. A and B must be
297
297
  ; of the same length. TODO: make this smarter (ranges, length mismatch)
298
298
  ; ! clobbers heap addresses -1, -2, and -3
299
- ; [S A B] => [S]
299
+ ; [S A B] => [S']
300
300
  ;
301
301
  ; ["abcd" "abc" "xyz"] => ["xyzd"]
302
302
  ; ["foobar" "oba" "ele"] => ["feeler"]
@@ -316,19 +316,20 @@ _strtrans_no: pop ret
316
316
 
317
317
  ; expands the length-2 string S to contain the intervening ASCII characters
318
318
  ; ! TODO: make this smarter; multiple ranges in one string
319
- ; [S] => [S, expanded]
319
+ ; [S] => [S']
320
320
  ;
321
321
  ; ["CJ"] => ["CDEFGHIJ"]
322
- ; ["DA"] => ["DE"] TODO: bug
322
+ ; ["DA"] => ["DCBA"]
323
323
  ; ["af"] => ["abcdef"]
324
324
  ; ["09"] => ["0123456789"]
325
+ ; ["90"] => ["9876543210"]
325
326
  ; ["(1"] => ["()*+,-./01"]
326
327
  strexpand:
327
328
  push 0 swap push 128 :divmod
328
329
  swap :range :strpack :strrev ret
329
330
 
330
331
  ; "squeezes" runs of the same character in string S to just one occurrence
331
- ; [S] => [S, squeezed]
332
+ ; [S] => [S']
332
333
  ;
333
334
  ; ["abc"] => ["abc"]
334
335
  ; ["foobar"] => ["fobar"]
@@ -1,11 +1,10 @@
1
1
  import io ; print, println
2
2
  import string ; strcat
3
+ import util ; die!
3
4
 
4
5
  assert_eq:
5
6
  dup copy 2 sub jz _assert_eq_yes
6
7
  push "expected " :print onum
7
8
  push ", got " :print onum
8
- push " for test " :strcat :print :println
9
- exit
10
-
9
+ push " for test " swap :strcat :die!
11
10
  _assert_eq_yes: pop pop pop ret