電卓プログラムの使用例として簡単なライブラリを作ってみました。
Calc> isEven(2); 1 Calc> isEven(3); 0 Calc> isOdd(4); 0 Calc> isOdd(5); 1 Calc> isPositive(10); 1 Calc> isPositive(-10); 0 Calc> isNegative(10); 0 Calc> isNegative(-10); 1 Calc> isZero(0); 1 Calc> isZero(-1); 0 Calc> abs(-10); 10 Calc> abs(10); 10 Calc> max(1, 10); 10 Calc> min(1, 10); 1 Calc> gcd(24, 32); 8 Calc> lcm(24, 32); 96 Calc> combNum(10, 5); 252 Calc> combNum(30,15); 155117520 Calc> fact(10); 3628800 Calc> fact(20); 2432902008176640000 Calc> expt(2,32); 4294967296 Calc> expt(2,62); 4611686018427387904 Calc> fibo(0); 1 Calc> fibo(1); 1 Calc> fibo(2); 2 Calc> fibo(10); 89 Calc> fibo(50); 20365011074 Calc> sieve(100); (2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97) Calc> factorization(1234567890); ((2 . 1) (3 . 2) (5 . 1) (3607 . 1) (3803 . 1)) Calc> factorization(1111111111); ((11 . 1) (41 . 1) (271 . 1) (9091 . 1))
Calc> pair(cons(1, 2)); 1 Calc> pair(nil); 0 Calc> null(nil); 1 Calc> null(cons(1, 2)); 0 Calc> any(isEven, list(1,3,5,7,9)); 0 Calc> any(isEven, list(1,3,4,5,7,9)); 1 Calc> any(isOdd, [2,4,6,8,10]); 0 Calc> any(isOdd, [2,4,5,6,8,10]); 1 Calc> every(isEven, list(2,4,6,8)); 1 Calc> every(isEven, list(2,4,5,6,8)); 0 Calc> every(isEven, [2,4,6,8,10]); 1 Calc> every(isEven, [2,4,6,8,10,11]); 0 Calc> eql(1, 1); 1 Calc> eql(1, 1.0); 0 Calc> eql("abc", "abc"); 1 Calc> eql("abc", "def"); 0 Calc> eql("abc", 2); 0 Calc> eql(nil, nil); 1 Calc> equal(1, 1); 1 Calc> equal(1, 1.0); 0 Calc> equal("abc", "abc"); 1 Calc> equal("abc", "def"); 0 Calc> equal("abc", 2); 0 Calc> equal(list(1,2,3), list(1,2,3)); 1 Calc> equal(list(1,2,3), list(1,2,3.0)); 0 Calc> equal([[1,2],[3,4]], [[1,2],[3,4]]); 1 Calc> equal([[1,2],[3,4]], [[1,2],[3.0,4]]); 0
Calc> a = list(1,2,3,4,5); (1 2 3 4 5) Calc> first(a); 1 Calc> second(a); 2 Calc> third(a); 3 Calc> fourth(a); 4 Calc> fifth(a); 5 Calc> nth(a, 0); 1 Calc> nth(a, 4); 5
Calc> cons(1, 2); (1 . 2) Calc> cons(2, cons(1, nil)); (2 1) Calc> makelist(10, 0); (0 0 0 0 0 0 0 0 0 0) Calc> iota(1, 10); (1 2 3 4 5 6 7 8 9 10) Calc> tabulate(fn(x) x * x end, 1, 10); (1 4 9 16 25 36 49 64 81 100)
Calc> a = iota(1, 4); (1 2 3 4) Calc> b = iota(5, 8); (5 6 7 8) Calc> append(a, b); (1 2 3 4 5 6 7 8) Calc> c = append(a, b); (1 2 3 4 5 6 7 8) Calc> revAppend(a, b); (4 3 2 1 5 6 7 8) Calc> length(c); 8 Calc> reverse(c); (8 7 6 5 4 3 2 1) Calc> c; (1 2 3 4 5 6 7 8) Calc> c = iota(1, 9); (1 2 3 4 5 6 7 8 9) Calc> drop(c, 3); (4 5 6 7 8 9) Calc> take(c, 3); (1 2 3) Calc> last(c, 3); (7 8 9) Calc> butlast(c, 3); (1 2 3 4 5 6) Calc> partition(isEven, c); ((2 4 6 8) 1 3 5 7 9) Calc> partition(isOdd, c); ((1 3 5 7 9) 2 4 6 8)
Calc> a = list(5,6,4,7,3,8,2,9,1); (5 6 4 7 3 8 2 9 1) Calc> b = [5,6,4,7,3,8,2,9,1]; [5, 6, 4, 7, 3, 8, 2, 9, 1] Calc> sum(a); 45 Calc> sum(b); 45 Calc> maximum(a); 9 Calc> maximum(b); 9 Calc> minimum(b); 1 Calc> minimum(a); 1 Calc> a = toList([1,2,3,4,5]); (1 2 3 4 5) Calc> toVector(a); [1, 2, 3, 4, 5] Calc> b = toList([1,[2,[3],4],5]); (1 (2 (3) 4) 5) Calc> toVector(b); [1, [2, [3], 4], 5] Calc> foreach(print, a); 12345678 Calc> foreach(print, [1,2,3,4,5,6,7,8]); 12345678 Calc> copy(list(1,2,3,4,5)); (1 2 3 4 5) Calc> copy([1,2,3,4,5]); [1, 2, 3, 4, 5]
Calc> a; (1 2 3 4 5 6 7 8 9) Calc> b; [1, 2, 3, 4, 5, 6, 7, 8, 9] Calc> findIf(isEven, a); 2 Calc> findIf(isEven, b); 2 Calc> findIf(fn(x) x == 10 end, a); () Calc> positionIf(isEven, b); 1 Calc> positionIf(isEven, a); 1 Calc> positionIf(fn(x) x == 10 end, a); -1 Calc> countIf(isEven, a); 4 Calc> countIf(isEven, b); 4 Calc> member(5, a); (5 6 7 8 9) Calc> member(10, a); ()
Calc> a = iota(1, 8); (1 2 3 4 5 6 7 8) Calc> map(fn(x) x * 2 end, a); (2 4 6 8 10 12 14 16) Calc> filter(isEven, a); (2 4 6 8) Calc> removeIf(isEven, a); (1 3 5 7) Calc> foldl(fn(x, a) cons(x, a) end, nil, iota(1, 8)); (8 7 6 5 4 3 2 1) Calc> foldr(fn(x, a) cons(x, a) end, nil, iota(1, 8)); (1 2 3 4 5 6 7 8)
Calc> a = zip(iota(1, 5), iota(11, 15)); ((1 . 11) (2 . 12) (3 . 13) (4 . 14) (5 . 15)) Calc> assoc(1, a); (1 . 11) Calc> assoc(5, a); (5 . 15) Calc> assoc(6, a); () Calc> assocIf(fn(x) x % 3 == 0 end, a); (3 . 13)
リストを集合として扱う関数で、リストには重複要素がないものとする。
Calc> a = removeDup(list(1,1,2,1,2,3,1,2,3,4,1,2,3,4)); (1 2 3 4) Calc> b = list(3,4,5,6); (3 4 5 6) Calc> union(a, b); (1 2 3 4 5 6) Calc> intersection(a, b); (3 4) Calc> difference(a, b); (1 2) Calc> difference(b, a); (5 6) Calc> product(list(1,2,3), list(4,5)); ((1 . 4) (1 . 5) (2 . 4) (2 . 5) (3 . 4) (3 . 5)) Calc> powerSet(list(1,2,3,4)); (() (4) (3) (3 4) (2) (2 4) (2 3) (2 3 4) (1) (1 4) (1 3) (1 3 4) (1 2) (1 2 4) (1 2 3) (1 2 3 4))
Calc> mergeList(list(1,3,5,7), list(2,4,6,8)); (1 2 3 4 5 6 7 8) Calc> insertSortList(list(1,3,5,7,2,4,6,8)); (1 2 3 4 5 6 7 8) Calc> mergeSortList(list(1,3,5,7,2,4,6,8)); (1 2 3 4 5 6 7 8) Calc> insertSort([1,3,5,7,2,4,6,8]); [1, 2, 3, 4, 5, 6, 7, 8] Calc> quickSort([1,3,5,7,2,4,6,8]); [1, 2, 3, 4, 5, 6, 7, 8]
Calc> permutation(print, 3, list(1,2,3)); (1 2 3)(1 3 2)(2 1 3)(2 3 1)(3 1 2)(3 2 1) Calc> combination(print, 3, list(1,2,3,4,5)); (1 2 3)(1 2 4)(1 2 5)(1 3 4)(1 3 5)(1 4 5)(2 3 4)(2 3 5)(2 4 5)(3 4 5)
Calc> s = makeStack(); (()) Calc> push(s, 1); (1) Calc> push(s, 2); (2 1) Calc> push(s, 3); (3 2 1) Calc> isEmptyStack(s); 0 Calc> top(s); 3 Calc> pop(s); 3 Calc> pop(s); 2 Calc> pop(s); 1 Calc> isEmptyStack(s); 1 Calc> q = makeQueue(); (()) Calc> enqueue(q, 1); (1) Calc> enqueue(q, 2); (2) Calc> enqueue(q, 3); (3) Calc> isEmptyQueue(q); 0 Calc> front(q); 1 Calc> dequeue(q); 1 Calc> dequeue(q); 2 Calc> dequeue(q); 3 Calc> isEmptyQueue(q); 1
乱数生成のアルゴリズムは線形合同法なので、乱数の品質はあまりよくない。
Calc> srand(clock()); 3979656540 Calc> let i = 0 in while i < 8 do println(rand()), i = i + 1 end end; 1580551853 1952172426 2688968067 1359605992 1461301705 3210973942 3827903743 4181785396 0 Calc> let i = 0 in while i < 8 do println(random()), i = i + 1 end end; 0.8788879301864654 0.9104500492103398 0.8744489091914147 0.3117089420557022 0.4249188455287367 0.7197418245486915 0.8480797538068146 0.020515683107078075 0
マスターマインド (数当てゲーム) です。lib.cal のあとに mastermind.cal をロードしてください。
C>calc8 lib.cal mastermind.cal Calc> mastermind(); [a,b,c,d]>>> [0,1,2,3]; 1 : [0, 1, 2, 3], Bulls; 0, Cows: 2 [a,b,c,d]>>> [4,5,6,7]; 2 : [4, 5, 6, 7], Bulls; 2, Cows: 0 [a,b,c,d]>>> [3,5,6,0]; 3 : [3, 5, 6, 0], Bulls; 1, Cows: 1 [a,b,c,d]>>> [1,3,6,7]; 4 : [1, 3, 6, 7], Bulls; 0, Cows: 0 [a,b,c,d]>>> [4,5,0,2]; Good Job!
// // lib.cal : 電卓プログラム用ライブラリ // // Copyright (C) 2014 Makoto Hiroi // // 数値計算 // // 述語 def isOdd(x) x % 2 != 0 end def isEven(x) x % 2 == 0 end def isPositive(x) x > 0 end def isNegative(x) x < 0 end def isZero(x) x == 0 end // 絶対値 def abs(x) if x < 0 then -x else x end end // 符号 def sign(x) if x > 0 then 1 else if x < 0 then -1 end end end // 最大値と最小値 def max(a, b) if a > b then a else b end end def min(a, b) if a < b then a else b end end // 最大公約数 def gcd(a, b) if b == 0 then a else gcd(b, a % b) end end // 最小公倍数 def lcm(a, b) a * b / gcd(a, b) end // 累乗 x ** y (y is Int) def expt(x, y) if y == 0 then 1 else if y == 1 then x else let z = expt(x, y / 2) in if isOdd(y) then z * z * x else z * z end end end end end // 階乗 def fact(n) let a = 1 in while n > 0 do a = a * n, n = n - 1 end, a end end // フィボナッチ関数 def fibo(n) let a = 1, b = 0, c = 0 in while n > 0 do c = a, a = a + b, b = c, n = n - 1 end, a end end // 組み合わせの数 def combNum(n, r) if n == 0 or r == 0 then 1 else combNum(n, r - 1) * (n - r + 1) / r end end // // 連結リスト // def caar(xs) car(car(xs)) end def cadr(xs) car(cdr(xs)) end def cdar(xs) cdr(car(xs)) end def cddr(xs) cdr(cdr(xs)) end // 述語 def isList(xs) pair(xs) or null(xs) end def equal(xs, ys) if isVec(xs) then if isVec(ys) and len(xs) == len(ys) then let r = 1, i = 0 in while i < len(xs) and r do if !equal(xs[i], ys[i]) then r = 0 else i = i + 1 end end, r end end else let r = 1 in while pair(xs) and pair(ys) and r do if !equal(car(xs), car(ys)) then r = 0 else begin xs = cdr(xs), ys = cdr(ys) end end end, if r then if !pair(xs) and !pair(ys) then eql(xs, ys) end end end end end // 高階関数 def map(f, xs) if null(xs) then nil else cons(f(car(xs)), map(f, cdr(xs))) end end def filter(f, xs) if null(xs) then nil else if f(car(xs)) then cons(car(xs), filter(f, cdr(xs))) else filter(f, cdr(xs)) end end end def foldl(f, a, xs) while !null(xs) do a = f(car(xs), a), xs = cdr(xs) end, a end def foldr(f, a, xs) if null(xs) then a else f(car(xs), foldr(f, a, cdr(xs))) end end def every(f, xs) let r = 1 in while pair(xs) and r do if !f(car(xs)) then r = 0 end, xs = cdr(xs) end, r end end def any(f, xs) let r = 0 in while pair(xs) and !r do if f(car(xs)) then r = 1 end, xs = cdr(xs) end, r end end // リストの参照 def nth(xs, n) while !null(xs) and n > 0 do xs = cdr(xs), n = n - 1 end, car(xs) end def first(xs) car(xs) end def second(xs) cadr(xs) end def third(xs) car(cddr(xs)) end def fourth(xs) nth(xs, 3) end def fifth(xs) nth(xs, 4) end // 長さ def length(xs) foldl(fn(x, a) a + 1 end, 0, xs) end // 反転 def reverse(xs) foldl(fn(x, a) cons(x, a) end, nil, xs) end // 連結 def append(xs, ys) if null(xs) then ys else cons(car(xs), append(cdr(xs), ys)) end end def revAppend(xs, ys) while !null(xs) do ys = cons(car(xs), ys), xs = cdr(xs) end, ys end // 削除 def remove(x, xs) foldr(fn(y, a) if eql(x, y) then a else cons(y, a) end end, nil, xs) end def removeIf(f, xs) foldr(fn(x, a) if f(x) then a else cons(x, a) end end, nil, xs) end // 先頭から n 個の要素を取り出す def take(xs, n) if n == 0 or null(xs) then nil else cons(car(xs), take(cdr(xs), n - 1)) end end // 先頭から n 個の要素を取り除く def drop(xs, n) while !null(xs) and n > 0 do xs = cdr(xs), n = n - 1 end, xs end // 末尾から n 個の要素を取り出す def last(xs, n) drop(xs, length(xs) - n) end // 末尾から n 個の要素を取り除く def butlast(xs, n) take(xs, length(xs) - n) end // リストの生成 def makelist(n, x) let xs = nil in while n > 0 do xs = cons(x, xs), n = n - 1 end, xs end end def iota(n, m) let xs = nil in while m >= n do xs = cons(m, xs), m = m - 1 end, xs end end def tabulate(f, n, m) let xs = nil in while m >= n do xs = cons(f(m), xs), m = m - 1 end, xs end end // リストの分割 def partition(f, xs) if null(xs) then list(nil) else let ys = partition(f, cdr(xs)) in if f(car(xs)) then cons(cons(car(xs), car(ys)), cdr(ys)) else cons(car(ys), cons(car(xs), cdr(ys))) end end end end // 探索 def member(x, ls) while !null(ls) and !eql(car(ls), x) do ls = cdr(ls) end, ls end def memberIf(f, ls) while !null(ls) and !f(car(ls)) do ls = cdr(ls) end, ls end // 連想リスト def zip(xs, ys) if null(xs) or null(ys) then nil else cons(cons(car(xs), car(ys)), zip(cdr(xs), cdr(ys))) end end def assoc(x, xs) while !null(xs) and !eql(caar(xs), x) do xs = cdr(xs) end, car(xs) end def assocIf(f, xs) while !null(xs) and !f(caar(xs)) do xs = cdr(xs) end, car(xs) end // // 集合演算 // // 重複要素を取り除く def removeDup(xs) foldr(fn(x, a) if member(x, a) then a else cons(x, a) end end, nil, xs) end // 集合の和 def union(xs, ys) foldr(fn(x, a) if member(x, ys) then a else cons(x, a) end end, ys, xs) end // 集合の積 def intersection(xs, ys) foldr(fn(x, a) if member(x, ys) then cons(x, a) else a end end, nil, xs) end // 集合の差 def difference(xs, ys) foldr(fn(x, a) if member(x, ys) then a else cons(x, a) end end, nil, xs) end // 直積集合 def product(xs, ys) foldr(fn(x, a) append(map(fn(y) cons(x, y) end, ys), a) end, nil, xs) end // べき集合 def powerSet(xs) if null(xs) then list(nil) else append(powerSet(cdr(xs)), map(fn(ys) cons(car(xs), ys) end, powerSet(cdr(xs)))) end end // // ベクタ // // 高階関数 def vectorFold(f, a, xs) let i = 0 in while i < len(xs) do a = f(xs[i], a), i = i + 1 end, a end end // // 列関数 // def selectFold(xs) if isList(xs) then foldl else if isVec(xs) then vectorFold else error("list or vector required") end end end def sum(xs) let f = selectFold(xs) in f(fn(x, y) x + y end, 0, xs) end end def maximum(xs) if pair(xs) then foldl(fn(x, a) max(x, a) end, car(xs), cdr(xs)) else if isVec(xs) then vectorFold(fn(x, a) max(x, a) end, xs[0], xs) else error("list or vector required") end end end def minimum(xs) if pair(xs) then foldl(fn(x, a) min(x, a) end, car(xs), cdr(xs)) else if isVec(xs) then vectorFold(fn(x, a) min(x, a) end, xs[0], xs) else error("list or vector required") end end end def positionIf(f, xs) let i = 0, r = 0 in if isList(xs) then while !null(xs) and !r do if f(car(xs)) then r = 1 else begin i = i + 1, xs = cdr(xs) end end end else if isVec(xs) then while i < len(xs) and !r do if f(xs[i]) then r = 1 else i = i + 1 end end else error("list or vector required") end end, if r then i else -1 end end end def position(x, xs) positionIf(fn(y) eql(x, y) end, xs) end def findIf(f, xs) if isList(xs) then car(memberIf(f, xs)) else if isVec(xs) then let i = positionIf(f, xs) in if i >= 0 then xs[i] else nil end end else error("list or vector required") end end end def find(x, xs) !null(findIf(fn(y) eql(x, y) end, xs)) end def countIf(f, xs) let g = selectFold(xs) in g(fn(x, a) if f(x) then a + 1 else a end end, 0, xs) end end def count(x, xs) countIf(fn(y) eql(x, y) end, xs) end // // リストとベクタの変換 // def toList(xs) let ys = nil, i = len(xs) - 1 in while i >= 0 do if isVec(xs[i]) then ys = cons(toList(xs[i]), ys) else ys = cons(xs[i], ys) end, i = i - 1 end, ys end end def toVector(xs) let ys = vector(length(xs), 0), i = 0 in while pair(xs) do if pair(car(xs)) then ys[i] = toVector(car(xs)) else ys[i] = car(xs) end, xs = cdr(xs), i = i + 1 end, ys end end // foreach と copy def foreach(f, xs) let g = selectFold(xs) in g(fn(x, a) f(x) end, 0, xs) end end def copy(xs) if isList(xs) then foldr(cons, nil, xs) else if isVec(xs) then let i = 0, ys = vector(len(xs), 0) in while i < len(xs) do ys[i] = xs[i], i = i + 1 end, ys end else error("list or vector required") end end end // // 順列と組み合わせ // def permSub(f, n, xs, a) if n == 0 then f(reverse(a)) else foreach(fn(x) permSub(f, n - 1, remove(x, xs), cons(x, a)) end, xs) end end def permutation(f, n, xs) permSub(f, n, xs, nil) end def combSub(f, n, xs, a) if n == 0 then f(reverse(a)) else if length(xs) == n then f(append(reverse(a), xs)) else begin combSub(f, n - 1, cdr(xs), cons(car(xs), a)), combSub(f, n, cdr(xs), a) end end end end def combination(f, n, xs) combSub(f, n, xs, nil) end // // 素数 // def sieve(n) let xs = iota(2, n), ys = nil in while car(xs) <= sqrt(n) do ys = cons(car(xs), ys), xs = removeIf(fn(x) x % car(xs) == 0 end, xs) end, revAppend(ys, xs) end end // 素因数分解 def factorSub(n, m) let c = 0 in while n % m == 0 do c = c + 1, n = n / m end, cons(c, n) end end def factorization(n) let xs = factorSub(n, 2), ys = if car(xs) != 0 then list(cons(2, car(xs))) else nil end, i = 3 in n = cdr(xs), while n >= i * i and n != 1 do xs = factorSub(n, i), if car(xs) != 0 then ys = cons(cons(i, car(xs)), ys) end, n = cdr(xs), i = i + 2 end, if n != 1 then ys = cons(cons(n, 1), ys) end, reverse(ys) end end // // 線形合同法による乱数の生成 // Seed = 1; Mask = 0x100000000; RandMax = Mask - 1; def srand(n) Seed = n % Mask end def rand() Seed = (69069 * Seed + 1) % Mask, Seed end def random() (1.0 / (RandMax + 1.0)) * rand() end // // マージとソート // def insertElement(x, xs) if null(xs) then list(x) else if x <= car(xs) then cons(x, xs) else cons(car(xs), insertElement(x, cdr(xs))) end end end def insertSortList(xs) let ys = nil in while !null(xs) do ys = insertElement(car(xs), ys), xs = cdr(xs) end, ys end end def mergeList(xs, ys) if null(xs) then ys else if null(ys) then xs else if car(xs) <= car(ys) then cons(car(xs), mergeList(cdr(xs), ys)) else cons(car(ys), mergeList(xs, cdr(ys))) end end end end // def mergeSortSub(n, xs) if n < 16 then insertSortList(take(xs, n)) else let m = n / 2 in mergeList(mergeSortSub(m, xs), mergeSortSub(n - m, drop(xs, m))) end end end def mergeSortList(xs) mergeSortSub(length(xs), xs) end // // ベクタのソート // // 単純挿入ソート def insertSort(v) let i = 1, k = len(v), j = 0, tmp = 0 in while i < k do j = i, tmp = v[i], while j > 0 and v[j - 1] >= tmp do v[j] = v[j - 1], j = j - 1 end, v[j] = tmp, i = i + 1 end end, v end // クイックソート def qsort(v, low, high) if high - low > 16 then let pivot = v[(low + high) / 2], flag = 1, i = low, j = high in while flag do while v[i] < pivot do i = i + 1 end, while pivot < v[j] do j = j - 1 end, if i < j then let tmp = v[i] in v[i] = v[j], v[j] = tmp, i = i + 1, j = j - 1 end else flag = 0 end end, qsort(v, low, i - 1), qsort(v, j + 1, high) end end end def quickSort(v) qsort(v, 0, len(v) - 1), insertSort(v) end // // スタックとキュー // def makeStack() list(nil) end def push(s, x) setCar(s, cons(x, car(s))) end def pop(s) if null(car(s)) then error("Stack is empty") else let x = caar(s) in setCar(s, cdar(s)), x end end end def top(s) if null(car(s)) then error("Stack is empty") else caar(s) end end def isEmptyStack(s) null(car(s)) end // キュー def makeQueue() cons(nil, nil) end def enqueue(q, x) let newCell = list(x) in if null(car(q)) then begin setCar(q, newCell), setCdr(q, newCell) end else begin setCdr(cdr(q), newCell), setCdr(q, newCell) end end end end def dequeue(q) if null(car(q)) then error("Queue is empty") else let x = car(q) in setCar(q, cdr(x)), if null(cdr(x)) then setCdr(q, nil) end, car(x) end end end def front(q) if null(car(q)) then error("Queue is empty") else caar(q) end end def isEmptyQueue(q) null(car(q)) end
// // mastermind.cal : 数当てゲーム // // Copyright (C) 2014 Makoto Hiroi // def makeQuestion() let xs = vector(4, -1), x = 0, n = 0 in while n < 4 do x = (rand() / 0x10000) % 10, if !find(x, xs) then begin xs[n] = x, n = n + 1 end end end, xs end end def countBulls(xs, ys) let c = 0, i = 0 in while i < 4 do if xs[i] == ys[i] then c = c + 1 end, i = i + 1 end, c end end def countSameNumber(xs, ys) let c = 0, i = 0 in while i < 4 do if find(xs[i], ys) then c = c + 1 end, i = i + 1 end, c end end def check(xs) if isVec(xs) and len(xs) == 4 then let i = 0, r = 1 in while i < 4 and r do if count(xs[i], xs) != 1 then r = 0 else i = i + 1 end end, r end end end def initRand(n) while n > 0 do rand(), n = n - 1 end end def mastermind() initRand(clock() % 0x100), let xs = makeQuestion(), ys = 0, r = 1 in while r do ys = input("[a,b,c,d]>>> "), if eql(ys, 0) then begin print("oops! : "), error(xs) end end, if !check(ys) then println("input error") else let bulls = countBulls(xs, ys), cows = countSameNumber(xs, ys) - bulls in if bulls == 4 then r = 0 else begin print(r), print(" : "), print(ys), print(", Bulls; "), print(bulls), print(", Cows: "), println(cows), r = r + 1 end end end end end, "Good Job!" end end