電卓プログラムの使用例として簡単なライブラリを作ってみました。
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); 0 Calc> fibo(1); 1 Calc> fibo(2); 1 Calc> fibo(10); 55 Calc> fibo(50); 12586269025 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> every(isEven, list(2,4,6,8));
1
Calc> every(isEven, list(2,4,5,6,8));
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(cons, nil, iota(1, 8)); (8 7 6 5 4 3 2 1) Calc> foldr(cons, 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 をロードしてください。
$ go run calc8.go 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-2021 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 = 0,
b = 1,
c = 0
in
while n > 0 do
c = a,
a = b,
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-2021 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