2016 Update

This commit is contained in:
Tina Müller 2016-12-05 22:15:40 +01:00
parent 948b86eafa
commit dcf5d15da3
7965 changed files with 139854 additions and 31002 deletions

View file

@ -1,11 +1,21 @@
Problem: You have 100 doors in a row that are all initially closed.
You make 100 [[task feature::Rosetta Code:multiple passes|passes]] by the doors.
The first time through, you visit every door and toggle the door (if the door is closed, you open it; if it is open, you close it). The second time you only visit every 2nd door (door #2, #4, #6, ...).
The third time, every 3rd door (door #3, #6, #9, ...), etc, until you only visit the 100th door.
There are 100 doors in a row that are all initially closed.
You make 100 [[task feature::Rosetta Code:multiple passes|passes]] by the doors.
The first time through, visit every door and   ''toggle''   the door   (if the door is closed,   open it;   if it is open,   close it).
The second time, only visit every 2<sup>nd</sup> door &nbsp; (door #2, #4, #6, ...), &nbsp; and toggle it.
The third time, visit every 3<sup>rd</sup> door &nbsp; (door #3, #6, #9, ...), etc, &nbsp; until you only visit the 100<sup>th</sup> door.
;Task:
Answer the question: &nbsp; what state are the doors in after the last pass? &nbsp; Which are open, which are closed?
Question: What state are the doors in after the last pass? Which are open, which are closed?
'''[[task feature::Rosetta Code:extra credit|Alternate]]:'''
As noted in this page's [[Talk:100 doors|discussion page]], the only doors that remain open are whose numbers are perfect squares of integers.
Opening only those doors is an [[task feature::Rosetta Code:optimization|optimization]] that may also be expressed;
As noted in this page's &nbsp; [[Talk:100 doors|discussion page]], &nbsp; the only doors that remain open are those whose numbers are perfect squares.
Opening only those doors is an &nbsp; [[task feature::Rosetta Code:optimization|optimization]] &nbsp; that may also be expressed;
however, as should be obvious, this defeats the intent of comparing implementations across programming languages.
<br><br>

View file

@ -0,0 +1,19 @@
# find the first few squares via the unoptimised door flipping method
scope
local doorMax := 100;
local door;
create register door( doorMax );
# set all doors to closed
for i to doorMax do door[ i ] := false od;
# repeatedly flip the doors
for i to doorMax do
for j from i to doorMax by i do door[ j ] := not door[ j ] od
od;
# display the results
for i to doorMax do if door[ i ] then write( " ", i ) fi od; print()
epocs

View file

@ -0,0 +1,149 @@
-- finalDoors :: Int -> [(Int, Bool)]
on finalDoors(n)
-- toggledCorridor :: [(Int, Bool)] -> (Int, Bool) -> Int -> [(Int, Bool)]
script toggledCorridor
on lambda(a, _, k)
-- perhapsToggled :: Bool -> Int -> Bool
script perhapsToggled
on lambda(x, i)
if i mod k = 0 then
{i, not item 2 of x}
else
{i, item 2 of x}
end if
end lambda
end script
map(perhapsToggled, a)
end lambda
end script
set lstRange to range(1, n)
foldl(toggledCorridor, ¬
zip(lstRange, replicate(n, {false})), lstRange)
end finalDoors
-- TEST
on run
-- isOpenAtEnd :: (Int, Bool) -> Bool
script isOpenAtEnd
on lambda(door)
(item 2 of door)
end lambda
end script
-- doorNumber :: (Int, Bool) -> Int
script doorNumber
on lambda(door)
(item 1 of door)
end lambda
end script
map(doorNumber, filter(isOpenAtEnd, finalDoors(100)))
--> {1, 4, 9, 16, 25, 36, 49, 64, 81, 100}
end run
-- GENERIC FUNCTIONS
-- filter :: (a -> Bool) -> [a] -> [a]
on filter(f, xs)
tell mReturn(f)
set lst to {}
set lng to length of xs
repeat with i from 1 to lng
set v to item i of xs
if lambda(v, i, xs) then set end of lst to v
end repeat
return lst
end tell
end filter
-- foldl :: (a -> b -> a) -> a -> [b] -> a
on foldl(f, startValue, xs)
tell mReturn(f)
set v to startValue
set lng to length of xs
repeat with i from 1 to lng
set v to lambda(v, item i of xs, i, xs)
end repeat
return v
end tell
end foldl
-- map :: (a -> b) -> [a] -> [b]
on map(f, xs)
tell mReturn(f)
set lng to length of xs
set lst to {}
repeat with i from 1 to lng
set end of lst to lambda(item i of xs, i, xs)
end repeat
return lst
end tell
end map
-- zip :: [a] -> [b] -> [(a, b)]
on zip(xs, ys)
script pair
on lambda(x, i)
[x, item i of ys]
end lambda
end script
if length of xs = length of ys then
map(pair, xs)
else
missing value
end if
end zip
-- Egyptian multiplication - progressively doubling a list, appending
-- stages of doubling to an accumulator where needed for binary
-- assembly of a target length
-- replicate :: Int -> a -> [a]
on replicate(n, a)
if class of a is list then
set out to {}
else
set out to ""
end if
if n < 1 then return out
set dbl to a
repeat while (n > 1)
if (n mod 2) > 0 then set out to out & dbl
set n to (n div 2)
set dbl to (dbl & dbl)
end repeat
return out & dbl
end replicate
-- range :: Int -> Int -> [Int]
on range(m, n)
set d to 1
if n < m then set d to -1
set lst to {}
repeat with i from m to n by d
set end of lst to i
end repeat
return lst
end range
-- Lift 2nd class handler function into 1st class script wrapper
-- mReturn :: Handler -> Script
on mReturn(f)
if class of f is script then
f
else
script
property lambda : f
end script
end if
end mReturn

View file

@ -0,0 +1 @@
{1, 4, 9, 16, 25, 36, 49, 64, 81, 100}

View file

@ -0,0 +1,5 @@
map(factorCountMod2, range(1, 100))
on factorCountMod2(n)
{n, (length of integerFactors(n)) mod 2 = 1}
end factorCountMod2

View file

@ -0,0 +1,21 @@
-- perfectSquaresUpTo :: Int -> [Int]
on perfectSquaresUpTo(n)
script squared
-- (Int -> Int)
on lambda(x)
x * x
end lambda
end script
set realRoot to n ^ (1 / 2)
set intRoot to realRoot as integer
set blnNotPerfectSquare to not (intRoot = realRoot)
map(squared, range(1, intRoot - (blnNotPerfectSquare as integer)))
end perfectSquaresUpTo
on run
perfectSquaresUpTo(100)
end run

View file

@ -0,0 +1 @@
{1, 4, 9, 16, 25, 36, 49, 64, 81, 100}

View file

@ -2,7 +2,7 @@
(->> (for [step (range 1 101), occ (range step 101 step)] occ)
frequencies
(filter (comp odd? val))
(map first)
keys
sort))
(defn print-open-doors []

View file

@ -4,7 +4,7 @@ var i, j : Integer;
for i := 1 to 100 do
for j := i to 100 do
if (j mod i) = 0 then
doors[j] := not doors[j];
doors[j] := not doors[j];F
for i := 1 to 100 do
if doors[i] then

View file

@ -1,6 +1,6 @@
#define system.
#define system'routines.
#define extensions.
#import system.
#import system'routines.
#import extensions.
#symbol program=
[

View file

@ -21,3 +21,5 @@ CONSTANT: number-of-doors 100
: main ( -- )
number-of-doors 1 + <bit-array>
[ toggle-all-multiples ] [ print-doors ] bi ;
main

View file

@ -1,22 +1,15 @@
PROGRAM DOORS
program doors
implicit none
integer, allocatable :: door(:)
character(6), parameter :: s(0:1) = ["closed", "open "]
integer :: i, n
INTEGER, PARAMETER :: n = 100 ! Number of doors
INTEGER :: i, j
LOGICAL :: door(n) = .TRUE. ! Initially closed
DO i = 1, n
DO j = i, n, i
door(j) = .NOT. door(j)
END DO
END DO
DO i = 1, n
WRITE(*,"(A,I3,A)", ADVANCE="NO") "Door ", i, " is "
IF (door(i)) THEN
WRITE(*,"(A)") "closed"
ELSE
WRITE(*,"(A)") "open"
END IF
END DO
END PROGRAM DOORS
print "(A)", "Number of doors?"
read *, n
allocate (door(n))
door = 1
do i = 1, n
door(i:n:i) = 1 - door(i:n:i)
print "(A,G0,2A)", "door ", i, " is ", s(door(i))
end do
end program

View file

@ -1,13 +1 @@
public class HundredDoors {
public static void main(String[] args) {
boolean[] doors = new boolean[101];
for (int i = 1; i <= 100; i++) {
for (int j = i; j <= 100; j++) {
if(j % i == 0) doors[j] = !doors[j];
}
}
for (int i = 1; i <= 100; i++) {
System.out.printf("Door %d: %s%n", i, doors[i] ? "open" : "closed");
}
}
}
N.println(IntStream.rangeClosed(1, 100).filter(i -> Math.pow((int) Math.sqrt(i), 2) == i).boxed().join(", ", "Open Doors: ", ""));

View file

@ -1,11 +1,13 @@
public class Doors
{
public static void main(String[] args)
{
boolean[] doors=new boolean[100];
for(int i=0;i<10;i++)
doors[i*(i+2)]=true;
for(int i=0;i<100;i++)
System.out.println("Door #"+(i+1)+" is"+(doors[i]?"open.":" closed."));
}
public class HundredDoors {
public static void main(String[] args) {
boolean[] doors = new boolean[101];
for (int i = 1; i <= 100; i++) {
for (int j = i; j <= 100; j++) {
if(j % i == 0) doors[j] = !doors[j];
}
}
for (int i = 1; i <= 100; i++) {
System.out.printf("Door %d: %s%n", i, doors[i] ? "open" : "closed");
}
}
}

View file

@ -2,7 +2,10 @@ public class Doors
{
public static void main(String[] args)
{
boolean[] doors=new boolean[100];
for(int i=0;i<10;i++)
System.out.println("Door #"+(i*(i+2)+1)+" is open.");
doors[i*(i+2)]=true;
for(int i=0;i<100;i++)
System.out.println("Door #"+(i+1)+" is"+(doors[i]?"open.":" closed."));
}
}

View file

@ -1,13 +1,8 @@
public class Doors
{
public static void main(final String[] args)
{
boolean[] doors = new boolean[100];
for (int pass = 0; pass < 10; pass++)
doors[(pass + 1) * (pass + 1) - 1] = true;
for(int i = 0; i < 100; i++)
System.out.println("Door #" + (i + 1) + " is " + (doors[i] ? "open." : "closed."));
}
public static void main(String[] args)
{
for(int i=0;i<10;i++)
System.out.println("Door #"+(i*(i+2)+1)+" is open.");
}
}

View file

@ -2,11 +2,12 @@ public class Doors
{
public static void main(final String[] args)
{
StringBuilder sb = new StringBuilder();
boolean[] doors = new boolean[100];
for (int i = 1; i <= 10; i++)
sb.append("Door #").append(i*i).append(" is open\n");
for (int pass = 0; pass < 10; pass++)
doors[(pass + 1) * (pass + 1) - 1] = true;
System.out.println(sb.toString());
for(int i = 0; i < 100; i++)
System.out.println("Door #" + (i + 1) + " is " + (doors[i] ? "open." : "closed."));
}
}

View file

@ -1,13 +1,12 @@
public class Doors{
public static void main(String[] args){
int i;
for(i = 1; i < 101; i++){
double sqrt = Math.sqrt(i);
if(sqrt != (int)sqrt){
System.out.println("Door " + i + " is closed");
}else{
System.out.println("Door " + i + " is open");
}
}
}
public class Doors
{
public static void main(final String[] args)
{
StringBuilder sb = new StringBuilder();
for (int i = 1; i <= 10; i++)
sb.append("Door #").append(i*i).append(" is open\n");
System.out.println(sb.toString());
}
}

View file

@ -0,0 +1,13 @@
public class Doors{
public static void main(String[] args){
int i;
for(i = 1; i < 101; i++){
double sqrt = Math.sqrt(i);
if(sqrt != (int)sqrt){
System.out.println("Door " + i + " is closed");
}else{
System.out.println("Door " + i + " is open");
}
}
}
}

View file

@ -1,14 +1,9 @@
(function () {
// Array comprehension style
[ for (i of Array.apply(null, { length: 100 })) i ].forEach((_, i) => {
var door = i + 1
var sqrt = Math.sqrt(door);
return rng(1, Math.sqrt(100)).map(function (x) {
return x * x;
});
// rng(1, 20) --> [1..20]
function rng(m, n) {
return Array.apply(null, Array(n - m + 1)).map(function (x, i) {
return m + i;
});
if (sqrt === (sqrt | 0)) {
console.log("Door %d is open", door);
}
})();
});

View file

@ -1 +1,29 @@
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
(function (n) {
// ONLY PERFECT SQUARES HAVE AN ODD NUMBER OF INTEGER FACTORS
// (Leaving the door open at the end of the process)
return perfectSquaresUpTo(n);
// perfectSquaresUpTo :: Int -> [Int]
function perfectSquaresUpTo(n) {
return range(1, Math.floor(Math.sqrt(n)))
.map(x => x * x);
}
// GENERIC
// range(intFrom, intTo, optional intStep)
// Int -> Int -> Maybe Int -> [Int]
function range(m, n, step) {
let d = (step || 1) * (n >= m ? 1 : -1);
return Array.from({
length: Math.floor((n - m) / d) + 1
}, (_, i) => m + (i * d));
}
})(100);

View file

@ -1,9 +1 @@
Array.apply(null, { length: 100 })
.map((v, i) => i + 1)
.forEach(door => {
var sqrt = Math.sqrt(door);
if (sqrt === (sqrt | 0)) {
console.log("Door %d is open", door);
}
});
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

View file

@ -1,41 +1,80 @@
(function () {
return chain(
(function (n) {
'use strict';
// 100 passes ...
rng(0, 99).reduce(function (a, _, i) {
return a.slice(0, i).concat(
a.slice(i).map(function (v, j) {
return (i + j + 1) % (i + 1) ? v : {
door: v.door,
open: !v.open
};
})
)
},
// 100 closed doors at start
Array.apply(null, Array(100)).map(function (x, i) {
return {
open: false,
door: i + 1
};
})),
// finalDoors :: Int -> [(Int, Bool)]
function finalDoors(n) {
var lstRange = range(1, n);
// Filtering by chained function
function (door) {
return door.open ? [door] : [];
return lstRange
.reduce(function (a, _, k) {
var m = k + 1;
return a.map(function (x, i) {
var j = i + 1;
return [j, j % m ? x[1] : !x[1]];
});
}, zip(
lstRange,
replicate(n, false)
));
};
// GENERIC FUNCTIONS
// zip :: [a] -> [b] -> [(a,b)]
function zip(xs, ys) {
return xs.length === ys.length ? (
xs.map(function (x, i) {
return [x, ys[i]];
})
) : undefined;
}
)
// Monadic bind (chain) for lists
function chain(xs, f) {
return [].concat.apply([], xs.map(f));
}
// replicate :: Int -> a -> [a]
function replicate(n, a) {
var v = [a],
o = [];
// range(1, 20) --> [1..20]
function rng(m, n) {
return Array.apply(null, Array(n - m + 1)).map(function (x, i) {
return m + i;
});
}
})();
if (n < 1) return o;
while (n > 1) {
if (n & 1) o = o.concat(v);
n >>= 1;
v = v.concat(v);
}
return o.concat(v);
}
// range(intFrom, intTo, optional intStep)
// Int -> Int -> Maybe Int -> [Int]
function range(m, n, delta) {
var d = delta || 1,
blnUp = n > m,
lng = Math.floor((blnUp ? n - m : m - n) / d) + 1,
a = Array(lng),
i = lng;
if (blnUp)
while (i--) a[i] = (d * i) + m;
else
while (i--) a[i] = m - (d * i);
return a;
}
return finalDoors(n)
.filter(function (tuple) {
return tuple[1];
})
.map(function (tuple) {
return {
door: tuple[0],
open: tuple[1]
};
});
})(100);

View file

@ -1,9 +1,44 @@
Array.apply(null, { length: 100 })
.map(function(v, i) { return i + 1; })
.forEach(function(door) {
var sqrt = Math.sqrt(door);
(function (n) {
'use strict';
if (sqrt === (sqrt | 0)) {
console.log("Door %d is open", door);
}
});
return range(1, 100)
.filter(function (x) {
return integerFactors(x)
.length % 2;
});
function integerFactors(n) {
var rRoot = Math.sqrt(n),
intRoot = Math.floor(rRoot),
lows = range(1, intRoot)
.filter(function (x) {
return (n % x) === 0;
});
// for perfect squares, we can drop the head of the 'highs' list
return lows.concat(lows.map(function (x) {
return n / x;
})
.reverse()
.slice((rRoot === intRoot) | 0));
}
// range(intFrom, intTo, optional intStep)
// Int -> Int -> Maybe Int -> [Int]
function range(m, n, delta) {
var d = delta || 1,
blnUp = n > m,
lng = Math.floor((blnUp ? n - m : m - n) / d) + 1,
a = Array(lng),
i = lng;
if (blnUp)
while (i--) a[i] = (d * i) + m;
else
while (i--) a[i] = m - (d * i);
return a;
}
})(100);

View file

@ -1,34 +1,31 @@
(function () {
return chain(
(function (n) {
'use strict';
rng(1, 100),
return perfectSquaresUpTo(100);
function (x) {
var root = Math.sqrt(x);
return root === Math.floor(root) ? inject(x) : fail();
function perfectSquaresUpTo(n) {
return range(1, Math.floor(Math.sqrt(n)))
.map(function (x) {
return x * x;
});
}
);
// GENERIC
/*************************************************************/
// range(intFrom, intTo, optional intStep)
// Int -> Int -> Maybe Int -> [Int]
function range(m, n, delta) {
var d = delta || 1,
blnUp = n > m,
lng = Math.floor((blnUp ? n - m : m - n) / d) + 1,
a = Array(lng),
i = lng;
// monadic Bind/chain for lists
function chain(xs, f) {
return [].concat.apply([], xs.map(f));
}
if (blnUp)
while (i--) a[i] = (d * i) + m;
else
while (i--) a[i] = m - (d * i);
return a;
}
// monadic Return/inject for lists
function inject(x) { return [x]; }
// monadic Fail for lists
function fail() { return []; }
// rng(1, 20) --> [1..20]
function rng(m, n) {
return Array.apply(null, Array(n - m + 1)).map(function (x, i) {
return m + i;
});
}
})();
})(100);

View file

@ -1,18 +1,9 @@
(function () {
Array.apply(null, { length: 100 })
.map((v, i) => i + 1)
.forEach(door => {
var sqrt = Math.sqrt(door);
return rng(1, 100).filter(
function (x) {
var root = Math.sqrt(x);
return root === Math.floor(root);
}
);
// rng(1, 20) --> [1..20]
function rng(m, n) {
return Array.apply(null, Array(n - m + 1)).map(function (x, i) {
return m + i;
if (sqrt === (sqrt | 0)) {
console.log("Door %d is open", door);
}
});
}
})();

View file

@ -1,11 +1,10 @@
fun oneHundredDoors(): List<Int> {
val doors = Array<Boolean>(100, { false })
val doors = BooleanArray(100, { false })
for (i in 0..99)
for (j in i..99 step (i + 1))
doors[j] = !doors[j]
return IndexIterator(doors.iterator()).filter { it.second }
.map { it.first + 1 }
.toList()
return doors.asSequence().mapIndexed { i, b -> i to b }.filter { it.second }
.map { it.first + 1 }.toList()
}

View file

@ -1,6 +1,4 @@
is_open = {}
for door = 1,100 do is_open[door] = false end
local is_open = {}
for pass = 1,100 do
for door = pass,100,pass do
@ -9,9 +7,5 @@ for pass = 1,100 do
end
for i,v in next,is_open do
if v then
print ('Door '..i..':','open')
else
print ('Door '..i..':', 'close')
end
print ('Door '..i..':',v and 'open' or 'close')
end

View file

@ -0,0 +1,8 @@
(define (status door-num)
(let ((x (int (sqrt door-num))))
(if
(= (* x x) door-num) (string "Door " door-num " Open")
(string "Door " door-num " Closed"))))
(dolist (n (map status (sequence 1 100)))
(println n))

View file

@ -0,0 +1,9 @@
(set 'Doors (array 100)) ;; Default value: nil (Closed)
(for (x 0 99)
(for (y x 99 (+ 1 x))
(setf (Doors y) (not (Doors y)))))
(for (x 0 99) ;; Display open doors
(if (Doors x)
(println (+ x 1) " : Open")))

View file

@ -0,0 +1,24 @@
type door = Open | Closed (* human readable code *)
let flipdoor = function Open -> Closed | Closed -> Open
let string_of_door =
function Open -> "is open." | Closed -> "is closed."
let printdoors ls =
let f i d = Printf.printf "Door %i %s\n" (i + 1) (string_of_door d)
in List.iteri f ls
let outerlim = 100
let innerlim = 100
let rec outer cnt accu =
let rec inner i door = match i > innerlim with (* define inner loop *)
| true -> door
| false -> inner (i + 1) (if (cnt mod i) = 0 then flipdoor door else door)
in (* define and do outer loop *)
match cnt > outerlim with
| true -> List.rev accu
| false -> outer (cnt + 1) (inner 1 Closed :: accu) (* generate new entries with inner *)
let () = printdoors (outer 1 [])

View file

@ -0,0 +1,9 @@
$Door dict def
1 1 100 {Door exch false put} for
$Toggle {dup Door exch get not Door up put} def
$EveryNthDoor {dup 100 {Toggle} for} def
$Run {1 1 100 {EveryNthDoor} for} def
$ShowDoor {dup `Door no. ' exch cvs cat ` is ' cat
exch Door exch get {`open.\n'}{`shut.\n'} ifelse cat
print flush} def
Run 1 1 100 {ShowDoor} for

View file

@ -0,0 +1,26 @@
sub output( @arr, $max ) {
my $output = 1;
for 1..^$max -> $index {
if @arr[$index] {
printf "%4d", $index;
say '' if $output++ %% 10;
}
}
say '';
}
sub MAIN ( Int :$doors = 100 ) {
my $doorcount = $doors + 1;
my @door[$doorcount] = 0 xx ($doorcount);
INDEX:
for 1...^$doorcount -> $index {
# flip door $index & its multiples, up to last door.
#
for ($index, * + $index ... *)[^$doors] -> $multiple {
next INDEX if $multiple > $doors;
@door[$multiple] = @door[$multiple] ?? 0 !! 1;
}
}
output @door, $doors+1;
}

View file

@ -0,0 +1,19 @@
boolean[] doors = new boolean[100];
void setup() {
for (int i = 0; i < 100; i++) {
doors[i] = false;
}
for (int i = 1; i < 100; i++) {
for (int j = 0; j < 100; j += i) {
doors[j] = !doors[j];
}
}
println("Open:");
for (int i = 1; i < 100; i++) {
if (doors[i]) {
println(i);
}
}
exit();
}

View file

@ -1,5 +1,5 @@
doors = [False] * 100
for i in xrange(100):
for j in xrange(i, 100, i+1):
doors[j] = not doors[j]
print "Door %d:" % (i+1), 'open' if doors[i] else 'close'
for i in range(100):
for j in range(i, 100, i+1):
doors[j] = not doors[j]
print("Door %d:" % (i+1), 'open' if doors[i] else 'close')

View file

@ -1,11 +1,17 @@
/*rexx*/
door. = 0
do inc = 1 to 100
do d = inc to 100 by inc
door.d = \door.d
end
end
say "The open doors after 100 passes:"
do i = 1 to 100
if door.i = 1 then say i
end
/*REXX pgm solves the 100 doors puzzle, doing it the hard way by opening/closing doors.*/
parse arg doors . /*obtain the optional argument from CL.*/
if doors=='' | doors=="," then doors=100 /*not specified? Then assume 100 doors*/
/* 0 = the door is closed. */
/* 1 = " " " open. */
door.=0 /*assume all doors are closed at start.*/
do #=1 for doors /*process a pass─through for all doors.*/
do j=# by # to doors /* ··· every Jth door from this point.*/
door.j= \door.j /*toggle the "openness" of the door. */
end /*j*/
end /*#*/
say 'After ' doors " passes, the following doors are open:"
say
do k=1 for doors
if door.k then say right(k, 20) /*add some indentation for the output. */
end /*k*/ /*stick a fork in it, we're all done. */

View file

@ -1,18 +1,8 @@
/*REXX program to solve the 100 door puzzle, the hard-way version. */
parse arg doors . /*get the first argument (# of doors.) */
if doors=='' then doors=100 /*not specified? Then assume 100 doors*/
/* 0 = closed. */
/* 1 = open. */
door.=0 /*assume all that all doors are closed.*/
do j=1 for doors /*process a pass-through for all doors.*/
do k=j by j to doors /* ... every Jth door from this point. */
door.k=\door.k /*toggle the "openness" of the door. */
end /*k*/
end /*j*/
/*REXX pgm solves the 100 doors puzzle, doing it the easy way by calculating squares.*/
parse arg doors . /*obtain the optional argument from CL.*/
if doors=='' | doors=="," then doors=100 /*not specified? Then assume 100 doors*/
say 'After ' doors " passes, the following doors are open:"
say
say 'After' doors "passes, the following doors are open:"
say
do n=1 for doors
if door.n then say right(n,20)
end /*n*/
do #=1 while #**2 <= doors /*process easy pass─through (squares).*/
say right(#**2, 20) /*add some indentation for the output. */
end /*#*/ /*stick a fork in it, we're all done. */

View file

@ -0,0 +1,5 @@
fn main() {
for i in 1u32..11u32{
println!("Door {} is open", i.pow(2));
}
}

View file

@ -0,0 +1,6 @@
(
var n = 100, doors = false ! n;
var pass = { |j| (0, j .. n-1).do { |i| doors[i] = doors[i].not } };
(1..n-1).do(pass);
doors.selectIndices { |open| open }; // all are closed except [ 0, 1, 4, 9, 16, 25, 36, 49, 64, 81 ]
)

View file

@ -11,3 +11,42 @@ For i = 1 To 100 Step 1
End If
Next i
End Sub
<!-- /lang -->
*** USE THIS ONE, SEE COMMENTED LINES, DONT KNOW WHY EVERYBODY FOLLOWED OTHERS ANSWERS AND CODED THE PROBLEM DIFFERENTLY ***
*** ALWAYS USE AND TEST A READABLE, EASY TO COMPREHEND CODING BEFORE 'OPTIMIZING' YOUR CODE AND TEST THE 'OPTIMIZED' CODE AGAINST THE 'READABLE' ONE.
Panikkos Savvides.
Sub Rosetta_100Doors2()
Dim Door(100) As Boolean, i As Integer, j As Integer
Dim strAns As String
' There are 100 doors in a row that are all initially closed.
' You make 100 passes by the doors.
For j = 1 To 100
' The first time through, visit every door and toggle the door
' (if the door is closed, open it; if it is open, close it).
For i = 1 To 100 Step 1
Door(i) = Not Door(i)
Next i
' The second time, only visit every 2nd door (door #2, #4, #6, ...), and toggle it.
For i = 2 To 100 Step 2
Door(i) = Not Door(i)
Next i
' The third time, visit every 3rd door (door #3, #6, #9, ...), etc, until you only visit the 100th door.
For i = 3 To 100 Step 3
Door(i) = Not Door(i)
Next i
Next j
For j = 1 To 100
If Door(j) = True Then
strAns = j & strAns & ", "
End If
Next j
If Right(strAns, 2) = ", " Then strAns = Left(strAns, Len(strAns) - 2)
If Len(strAns) = 0 Then strAns = "0"
Debug.Print "Doors [" & strAns & "] are open, the rest are closed."
' Doors [0] are open, the rest are closed., AKA ZERO DOORS OPEN
End Sub

View file

@ -1,5 +1,9 @@
;task:
Write a program that takes four digits, either from user input or by random generation, and computes arithmetic expressions following the rules of the [[24 game]].
Show examples of solutions generated by the program.
C.F: [[Arithmetic Evaluator]]
;Related task:
* &nbsp; [[Arithmetic Evaluator]]
<br><br>

View file

@ -0,0 +1,446 @@
>>SOURCE FORMAT FREE
*> This code is dedicated to the public domain
*> This is GNUCobol 2.0
identification division.
program-id. twentyfoursolve.
environment division.
configuration section.
repository. function all intrinsic.
input-output section.
file-control.
select count-file
assign to count-file-name
file status count-file-status
organization line sequential.
data division.
file section.
fd count-file.
01 count-record pic x(7).
working-storage section.
01 count-file-name pic x(64) value 'solutioncounts'.
01 count-file-status pic xx.
01 command-area.
03 nd pic 9.
03 number-definition.
05 n occurs 4 pic 9.
03 number-definition-9 redefines number-definition
pic 9(4).
03 command-input pic x(16).
03 command pic x(5).
03 number-count pic 9999.
03 l1 pic 99.
03 l2 pic 99.
03 expressions pic zzz,zzz,zz9.
01 number-validation.
03 px pic 99.
03 permutations value
'1234'
& '1243'
& '1324'
& '1342'
& '1423'
& '1432'
& '2134'
& '2143'
& '2314'
& '2341'
& '2413'
& '2431'
& '3124'
& '3142'
& '3214'
& '3241'
& '3423'
& '3432'
& '4123'
& '4132'
& '4213'
& '4231'
& '4312'
& '4321'.
05 permutation occurs 24 pic x(4).
03 cpx pic 9.
03 current-permutation pic x(4).
03 od1 pic 9.
03 od2 pic 9.
03 od3 pic 9.
03 operator-definitions pic x(4) value '+-*/'.
03 cox pic 9.
03 current-operators pic x(3).
03 rpn-forms value
'nnonono'
& 'nnonnoo'
& 'nnnonoo'
& 'nnnoono'
& 'nnnnooo'.
05 rpn-form occurs 5 pic x(7).
03 rpx pic 9.
03 current-rpn-form pic x(7).
01 calculation-area.
03 oqx pic 99.
03 output-queue pic x(7).
03 work-number pic s9999.
03 top-numerator pic s9999 sign leading separate.
03 top-denominator pic s9999 sign leading separate.
03 rsx pic 9.
03 result-stack occurs 8.
05 numerator pic s9999.
05 denominator pic s9999.
03 divide-by-zero-error pic x.
01 totals.
03 s pic 999.
03 s-lim pic 999 value 600.
03 s-max pic 999 value 0.
03 solution occurs 600 pic x(7).
03 sc pic 999.
03 sc1 pic 999.
03 sc2 pic 9.
03 sc-max pic 999 value 0.
03 sc-lim pic 999 value 600.
03 solution-counts value zeros.
05 solution-count occurs 600 pic 999.
03 ns pic 9999.
03 ns-max pic 9999 value 0.
03 ns-lim pic 9999 value 6561.
03 number-solutions occurs 6561.
05 ns-number pic x(4).
05 ns-count pic 999.
03 record-counts pic 9999.
03 total-solutions pic 9999.
01 infix-area.
03 i pic 9.
03 i-s pic 9.
03 i-s1 pic 9.
03 i-work pic x(16).
03 i-stack occurs 7 pic x(13).
procedure division.
start-twentyfoursolve.
display 'start twentyfoursolve'
perform display-instructions
perform get-command
perform until command-input = spaces
display space
initialize command number-count
unstring command-input delimited by all space
into command number-count
move command-input to number-definition
move spaces to command-input
evaluate command
when 'h'
when 'help'
perform display-instructions
when 'list'
if ns-max = 0
perform load-solution-counts
end-if
perform list-counts
when 'show'
if ns-max = 0
perform load-solution-counts
end-if
perform show-numbers
when other
if number-definition-9 not numeric
display 'invalid number'
else
perform get-solutions
perform display-solutions
end-if
end-evaluate
if command-input = spaces
perform get-command
end-if
end-perform
display 'exit twentyfoursolve'
stop run
.
display-instructions.
display space
display 'enter a number <n> as four integers from 1-9 to see its solutions'
display 'enter list to see counts of solutions for all numbers'
display 'enter show <n> to see numbers having <n> solutions'
display '<enter> ends the program'
.
get-command.
display space
move spaces to command-input
display '(h for help)?' with no advancing
accept command-input
.
ask-for-more.
display space
move 0 to l1
add 1 to l2
if l2 = 10
display 'more (<enter>)?' with no advancing
accept command-input
move 0 to l2
end-if
.
list-counts.
add 1 to sc-max giving sc
display 'there are ' sc ' solution counts'
display space
display 'solutions/numbers'
move 0 to l1
move 0 to l2
perform varying sc from 1 by 1 until sc > sc-max
or command-input <> spaces
if solution-count(sc) > 0
subtract 1 from sc giving sc1 *> offset to capture zero counts
display sc1 '/' solution-count(sc) space with no advancing
add 1 to l1
if l1 = 8
perform ask-for-more
end-if
end-if
end-perform
if l1 > 0
display space
end-if
.
show-numbers. *> with number-count solutions
add 1 to number-count giving sc1 *> offset for zero count
evaluate true
when number-count >= sc-max
display 'no number has ' number-count ' solutions'
exit paragraph
when solution-count(sc1) = 1 and number-count = 1
display '1 number has 1 solution'
when solution-count(sc1) = 1
display '1 number has ' number-count ' solutions'
when number-count = 1
display solution-count(sc1) ' numbers have 1 solution'
when other
display solution-count(sc1) ' numbers have ' number-count ' solutions'
end-evaluate
display space
move 0 to l1
move 0 to l2
perform varying ns from 1 by 1 until ns > ns-max
or command-input <> spaces
if ns-count(ns) = number-count
display ns-number(ns) space with no advancing
add 1 to l1
if l1 = 14
perform ask-for-more
end-if
end-if
end-perform
if l1 > 0
display space
end-if
.
display-solutions.
evaluate s-max
when 0 display number-definition ' has no solutions'
when 1 display number-definition ' has 1 solution'
when other display number-definition ' has ' s-max ' solutions'
end-evaluate
display space
move 0 to l1
move 0 to l2
perform varying s from 1 by 1 until s > s-max
or command-input <> spaces
*> convert rpn solution(s) to infix
move 0 to i-s
perform varying i from 1 by 1 until i > 7
if solution(s)(i:1) >= '1' and <= '9'
add 1 to i-s
move solution(s)(i:1) to i-stack(i-s)
else
subtract 1 from i-s giving i-s1
move spaces to i-work
string '(' i-stack(i-s1) solution(s)(i:1) i-stack(i-s) ')'
delimited by space into i-work
move i-work to i-stack(i-s1)
subtract 1 from i-s
end-if
end-perform
display solution(s) space i-stack(1) space space with no advancing
add 1 to l1
if l1 = 3
perform ask-for-more
end-if
end-perform
if l1 > 0
display space
end-if
.
load-solution-counts.
move 0 to ns-max *> numbers and their solution count
move 0 to sc-max *> solution counts
move spaces to count-file-status
open input count-file
if count-file-status <> '00'
perform create-count-file
move 0 to ns-max *> numbers and their solution count
move 0 to sc-max *> solution counts
open input count-file
end-if
read count-file
move 0 to record-counts
move zeros to solution-counts
perform until count-file-status <> '00'
add 1 to record-counts
perform increment-ns-max
move count-record to number-solutions(ns-max)
add 1 to ns-count(ns-max) giving sc *> offset 1 for zero counts
if sc > sc-lim
display 'sc ' sc ' exceeds sc-lim ' sc-lim
stop run
end-if
if sc > sc-max
move sc to sc-max
end-if
add 1 to solution-count(sc)
read count-file
end-perform
close count-file
.
create-count-file.
open output count-file
display 'Counting solutions for all numbers'
display 'We will examine 9*9*9*9 numbers'
display 'For each number we will examine 4! permutations of the digits'
display 'For each permutation we will examine 4*4*4 combinations of operators'
display 'For each permutation and combination we will examine 5 rpn forms'
display 'We will count the number of unique solutions for the given number'
display 'Each number and its counts will be written to file ' trim(count-file-name)
compute expressions = 9*9*9*9*factorial(4)*4*4*4*5
display 'So we will evaluate ' trim(expressions) ' statements'
display 'This will take a few minutes'
display 'In the future if ' trim(count-file-name) ' exists, this step will be bypassed'
move 0 to record-counts
move 0 to total-solutions
perform varying n(1) from 1 by 1 until n(1) = 0
perform varying n(2) from 1 by 1 until n(2) = 0
display n(1) n(2) '..' *> show progress
perform varying n(3) from 1 by 1 until n(3) = 0
perform varying n(4) from 1 by 1 until n(4) = 0
perform get-solutions
perform increment-ns-max
move number-definition to ns-number(ns-max)
move s-max to ns-count(ns-max)
move number-solutions(ns-max) to count-record
write count-record
add s-max to total-solutions
add 1 to record-counts
add 1 to ns-count(ns-max) giving sc *> offset by 1 for zero counts
if sc > sc-lim
display 'error: ' sc ' solution count exceeds ' sc-lim
stop run
end-if
add 1 to solution-count(sc)
end-perform
end-perform
end-perform
end-perform
close count-file
display record-counts ' numbers and counts written to ' trim(count-file-name)
display total-solutions ' total solutions'
display space
.
increment-ns-max.
if ns-max >= ns-lim
display 'error: numbers exceeds ' ns-lim
stop run
end-if
add 1 to ns-max
.
get-solutions.
move 0 to s-max
perform varying px from 1 by 1 until px > 24
move permutation(px) to current-permutation
perform varying od1 from 1 by 1 until od1 > 4
move operator-definitions(od1:1) to current-operators(1:1)
perform varying od2 from 1 by 1 until od2 > 4
move operator-definitions(od2:1) to current-operators(2:1)
perform varying od3 from 1 by 1 until od3 > 4
move operator-definitions(od3:1) to current-operators(3:1)
perform varying rpx from 1 by 1 until rpx > 5
move rpn-form(rpx) to current-rpn-form
move 0 to cpx cox
move spaces to output-queue
perform varying oqx from 1 by 1 until oqx > 7
if current-rpn-form(oqx:1) = 'n'
add 1 to cpx
move current-permutation(cpx:1) to nd
move n(nd) to output-queue(oqx:1)
else
add 1 to cox
move current-operators(cox:1) to output-queue(oqx:1)
end-if
end-perform
perform evaluate-rpn
if divide-by-zero-error = space
and 24 * top-denominator = top-numerator
perform varying s from 1 by 1 until s > s-max
or solution(s) = output-queue
continue
end-perform
if s > s-max
if s >= s-lim
display 'error: solutions ' s ' for ' number-definition ' exceeds ' s-lim
stop run
end-if
move s to s-max
move output-queue to solution(s-max)
end-if
end-if
end-perform
end-perform
end-perform
end-perform
end-perform
.
evaluate-rpn.
move space to divide-by-zero-error
move 0 to rsx *> stack depth
perform varying oqx from 1 by 1 until oqx > 7
if output-queue(oqx:1) >= '1' and <= '9'
*> push the digit onto the stack
add 1 to rsx
move top-numerator to numerator(rsx)
move top-denominator to denominator(rsx)
move output-queue(oqx:1) to top-numerator
move 1 to top-denominator
else
*> apply the operation
evaluate output-queue(oqx:1)
when '+'
compute top-numerator = top-numerator * denominator(rsx)
+ top-denominator * numerator(rsx)
compute top-denominator = top-denominator * denominator(rsx)
when '-'
compute top-numerator = top-denominator * numerator(rsx)
- top-numerator * denominator(rsx)
compute top-denominator = top-denominator * denominator(rsx)
when '*'
compute top-numerator = top-numerator * numerator(rsx)
compute top-denominator = top-denominator * denominator(rsx)
when '/'
compute work-number = numerator(rsx) * top-denominator
compute top-denominator = denominator(rsx) * top-numerator
if top-denominator = 0
move 'y' to divide-by-zero-error
exit paragraph
end-if
move work-number to top-numerator
end-evaluate
*> pop the stack
subtract 1 from rsx
end-if
end-perform
.
end program twentyfoursolve.

View file

@ -0,0 +1,46 @@
defmodule Game24 do
@expressions [ ["((", "", ")", "", ")", ""],
["(", "(", "", "", "))", ""],
["(", "", ")", "(", "", ")"],
["", "((", "", "", ")", ")"],
["", "(", "", "(", "", "))"] ]
def solve(digits) do
dig_perm = permute(digits) |> Enum.uniq
operators = perm_rep(~w[+ - * /], 3)
for dig <- dig_perm, ope <- operators, expr <- @expressions,
check?(str = make_expr(dig, ope, expr)),
do: str
end
defp check?(str) do
try do
{val, _} = Code.eval_string(str)
val == 24
rescue
ArithmeticError -> false # division by zero
end
end
defp permute([]), do: [[]]
defp permute(list) do
for x <- list, y <- permute(list -- [x]), do: [x|y]
end
defp perm_rep([], _), do: [[]]
defp perm_rep(_, 0), do: [[]]
defp perm_rep(list, i) do
for x <- list, y <- perm_rep(list, i-1), do: [x|y]
end
defp make_expr([a,b,c,d], [x,y,z], [e0,e1,e2,e3,e4,e5]) do
e0 <> a <> x <> e1 <> b <> e2 <> y <> e3 <> c <> e4 <> z <> d <> e5
end
end
case Game24.solve(System.argv) do
[] -> IO.puts "no solutions"
solutions ->
IO.puts "found #{length(solutions)} solutions, including #{hd(solutions)}"
IO.inspect Enum.sort(solutions)
end

View file

@ -1,18 +1,19 @@
use MONKEY-SEE-NO-EVAL;
my @digits;
my $amount = 4;
# Get $amount digits from the user,
# ask for more if they don't supply enough
while @digits.elems < $amount {
@digits ,= (prompt "Enter {$amount - @digits} digits from 1 to 9, "
@digits.append: (prompt "Enter {$amount - @digits} digits from 1 to 9, "
~ '(repeats allowed): ').comb(/<[1..9]>/);
}
# Throw away any extras
@digits = @digits[^$amount];
# Generate combinations of operators
my @op = <+ - * />;
my @ops = map {my $a = $_; map {my $b = $_; map {[$a,$b,$_]}, @op}, @op}, @op;
my @ops = [X,] <+ - * /> xx 3;
# Enough sprintf formats to cover most precedence orderings
my @formats = (
@ -26,34 +27,16 @@ my @formats = (
);
# Brute force test the different permutations
for unique permutations @digits -> @p {
for unique @digits.permutations -> @p {
for @ops -> @o {
for @formats -> $format {
my $string = sprintf $format, @p[0], @o[0],
@p[1], @o[1], @p[2], @o[2], @p[3];
my $result = try { EVAL($string) };
my $string = sprintf $format, flat roundrobin(|@p; |@o);
my $result = EVAL($string);
say "$string = 24" and last if $result and $result == 24;
}
}
}
# Perl 6 translation of Fischer-Krause ordered permutation algorithm
sub permutations (@array) {
my @index = ^@array;
my $last = @index[*-1];
my (@permutations, $rev, $fwd);
loop {
push @permutations, [@array[@index]];
$rev = $last;
--$rev while $rev and @index[$rev-1] > @index[$rev];
return @permutations unless $rev;
$fwd = $rev;
push @index, @index.splice($rev).reverse;
++$fwd while @index[$rev-1] > @index[$fwd];
@index[$rev-1,$fwd] = @index[$fwd,$rev-1];
}
}
# Only return unique sub-arrays
sub unique (@array) {
my %h = map { $_.Str => $_ }, @array;

View file

@ -1,29 +1,22 @@
class TwentyFourGamePlayer
class TwentyFourGame
EXPRESSIONS = [
'((%d %s %d) %s %d) %s %d',
'(%d %s (%d %s %d)) %s %d',
'(%d %s %d) %s (%d %s %d)',
'%d %s ((%d %s %d) %s %d)',
'%d %s (%d %s (%d %s %d))',
].map{|expr| [expr, expr.gsub('%d', 'Rational(%d,1)')]}
'((%dr %s %dr) %s %dr) %s %dr',
'(%dr %s (%dr %s %dr)) %s %dr',
'(%dr %s %dr) %s (%dr %s %dr)',
'%dr %s ((%dr %s %dr) %s %dr)',
'%dr %s (%dr %s (%dr %s %dr))',
]
OPERATORS = [:+, :-, :*, :/].repeated_permutation(3)
OBJECTIVE = Rational(24,1)
OPERATORS = [:+, :-, :*, :/].repeated_permutation(3).to_a
def self.solve(digits)
solutions = []
digits.permutation.to_a.uniq.each do |a,b,c,d|
OPERATORS.each do |op1,op2,op3|
EXPRESSIONS.each do |expr,expr_rat|
# evaluate using rational arithmetic
test = expr_rat % [a, op1, b, op2, c, op3, d]
value = eval(test) rescue -1 # catch division by zero
if value == OBJECTIVE
solutions << expr % [a, op1, b, op2, c, op3, d]
end
end
end
perms = digits.permutation.to_a.uniq
perms.product(OPERATORS, EXPRESSIONS) do |(a,b,c,d), (op1,op2,op3), expr|
# evaluate using rational arithmetic
text = expr % [a, op1, b, op2, c, op3, d]
value = eval(text) rescue next # catch division by zero
solutions << text.delete("r") if value == 24
end
solutions
end
@ -39,7 +32,7 @@ digits = ARGV.map do |arg|
end
digits.size == 4 or raise "error: need 4 digits, only have #{digits.size}"
solutions = TwentyFourGamePlayer.solve(digits)
solutions = TwentyFourGame.solve(digits)
if solutions.empty?
puts "no solutions"
else

View file

@ -1,18 +1,28 @@
The [[wp:24 Game|24 Game]] tests one's mental arithmetic.
Write a program that [[task feature::Rosetta Code:randomness|randomly]] chooses and [[task feature::Rosetta Code:user output|displays]] four digits, each from one to nine, with repetitions allowed. The program should prompt for the player to enter an arithmetic expression using ''just'' those, and ''all'' of those four digits, used exactly ''once'' each. The program should ''check'' then [[task feature::Rosetta Code:parsing|evaluate the expression]].
The goal is for the player to [[task feature::Rosetta Code:user input|enter]] an expression that evaluates to '''24'''.
* Only multiplication, division, addition, and subtraction operators/functions are allowed.
* Division should use floating point or rational arithmetic, etc, to preserve remainders.
* Brackets are allowed, if using an infix expression evaluator.
* Forming multiple digit numbers from the supplied digits is ''disallowed''. (So an answer of 12+12 when given 1, 2, 2, and 1 is wrong).
* The order of the digits when given does not have to be preserved.
Note:
;Task
Write a program that [[task feature::Rosetta Code:randomness|randomly]] chooses and [[task feature::Rosetta Code:user output|displays]] four digits, each from 1 ──► 9 (inclusive) with repetitions allowed.
The program should prompt for the player to enter an arithmetic expression using ''just'' those, and ''all'' of those four digits, used exactly ''once'' each. The program should ''check'' then [[task feature::Rosetta Code:parsing|evaluate the expression]].
The goal is for the player to [[task feature::Rosetta Code:user input|enter]] an expression that (numerically) evaluates to '''24'''.
* Only the following operators/functions are allowed: multiplication, division, addition, subtraction
* Division should use floating point or rational arithmetic, etc, to preserve remainders.
* Brackets are allowed, if using an infix expression evaluator.
* Forming multiple digit numbers from the supplied digits is ''disallowed''. (So an answer of 12+12 when given 1, 2, 2, and 1 is wrong).
* The order of the digits when given does not have to be preserved.
<br>
;Notes
* The type of expression evaluator used is not mandated. An [[wp:Reverse Polish notation|RPN]] evaluator is equally acceptable for example.
* The task is not for the program to generate the expression, or test whether an expression is even possible.
C.f: [[24 game Player]]
'''Reference'''
# [http://www.bbc.co.uk/dna/h2g2/A933121 The 24 Game] on h2g2.
;Related tasks
* [[24 game/Solve]]
;Reference
* [http://www.bbc.co.uk/dna/h2g2/A933121 The 24 Game] on h2g2.
<br><br>

View file

@ -0,0 +1,843 @@
>>SOURCE FORMAT FREE
*> This code is dedicated to the public domain
*> This is GNUCobol 2.0
identification division.
program-id. twentyfour.
environment division.
configuration section.
repository. function all intrinsic.
data division.
working-storage section.
01 p pic 999.
01 p1 pic 999.
01 p-max pic 999 value 38.
01 program-syntax pic x(494) value
*>statement = expression;
'001 001 000 n'
& '002 000 004 ='
& '003 005 000 n'
& '004 000 002 ;'
*>expression = term, {('+'|'-') term,};
& '005 005 000 n'
& '006 000 016 ='
& '007 017 000 n'
& '008 000 015 {'
& '009 011 013 ('
& '010 001 000 t'
& '011 013 000 |'
& '012 002 000 t'
& '013 000 009 )'
& '014 017 000 n'
& '015 000 008 }'
& '016 000 006 ;'
*>term = factor, {('*'|'/') factor,};
& '017 017 000 n'
& '018 000 028 ='
& '019 029 000 n'
& '020 000 027 {'
& '021 023 025 ('
& '022 003 000 t'
& '023 025 000 |'
& '024 004 000 t'
& '025 000 021 )'
& '026 029 000 n'
& '027 000 020 }'
& '028 000 018 ;'
*>factor = ('(' expression, ')' | digit,);
& '029 029 000 n'
& '030 000 038 ='
& '031 035 037 ('
& '032 005 000 t'
& '033 005 000 n'
& '034 006 000 t'
& '035 037 000 |'
& '036 000 000 n'
& '037 000 031 )'
& '038 000 030 ;'.
01 filler redefines program-syntax.
03 p-entry occurs 038.
05 p-address pic 999.
05 filler pic x.
05 p-definition pic 999.
05 p-alternate redefines p-definition pic 999.
05 filler pic x.
05 p-matching pic 999.
05 filler pic x.
05 p-symbol pic x.
01 t pic 999.
01 t-len pic 99 value 6.
01 terminal-symbols
pic x(210) value
'01 + '
& '01 - '
& '01 * '
& '01 / '
& '01 ( '
& '01 ) '.
01 filler redefines terminal-symbols.
03 terminal-symbol-entry occurs 6.
05 terminal-symbol-len pic 99.
05 filler pic x.
05 terminal-symbol pic x(32).
01 nt pic 999.
01 nt-lim pic 99 value 5.
01 nonterminal-statements pic x(294) value
"000 ....,....,....,....,....,....,....,....,....,"
& "001 statement = expression; "
& "005 expression = term, {('+'|'-') term,}; "
& "017 term = factor, {('*'|'/') factor,}; "
& "029 factor = ('(' expression, ')' | digit,); "
& "036 digit; ".
01 filler redefines nonterminal-statements.
03 nonterminal-statement-entry occurs 5.
05 nonterminal-statement-number pic 999.
05 filler pic x.
05 nonterminal-statement pic x(45).
01 indent pic x(64) value all '| '.
01 interpreter-stack.
03 r pic 99. *> previous top of stack
03 s pic 99. *> current top of stack
03 s-max pic 99 value 32.
03 s-entry occurs 32.
05 filler pic x(2) value 'p='.
05 s-p pic 999. *> callers return address
05 filler pic x(4) value ' sc='.
05 s-start-control pic 999. *> sequence start address
05 filler pic x(4) value ' ec='.
05 s-end-control pic 999. *> sequence end address
05 filler pic x(4) value ' al='.
05 s-alternate pic 999. *> the next alternate
05 filler pic x(3) value ' r='.
05 s-result pic x. *> S success, F failure, N no result
05 filler pic x(3) value ' c='.
05 s-count pic 99. *> successes in a sequence
05 filler pic x(3) value ' x='.
05 s-repeat pic 99. *> repeats in a {} sequence
05 filler pic x(4) value ' nt='.
05 s-nt pic 99. *> current nonterminal
01 language-area.
03 l pic 99.
03 l-lim pic 99.
03 l-len pic 99 value 1.
03 nd pic 9.
03 number-definitions.
05 n occurs 4 pic 9.
03 nu pic 9.
03 number-use.
05 u occurs 4 pic x.
03 statement.
05 c occurs 32.
07 c9 pic 9.
01 number-validation.
03 p4 pic 99.
03 p4-lim pic 99 value 24.
03 permutations-4 pic x(96) value
'1234'
& '1243'
& '1324'
& '1342'
& '1423'
& '1432'
& '2134'
& '2143'
& '2314'
& '2341'
& '2413'
& '2431'
& '3124'
& '3142'
& '3214'
& '3241'
& '3423'
& '3432'
& '4123'
& '4132'
& '4213'
& '4231'
& '4312'
& '4321'.
03 filler redefines permutations-4.
05 permutation-4 occurs 24 pic x(4).
03 current-permutation-4 pic x(4).
03 cpx pic 9.
03 od1 pic 9.
03 od2 pic 9.
03 odx pic 9.
03 od-lim pic 9 value 4.
03 operator-definitions pic x(4) value '+-*/'.
03 current-operators pic x(3).
03 co3 pic 9.
03 rpx pic 9.
03 rpx-lim pic 9 value 4.
03 valid-rpn-forms pic x(28) value
'nnonono'
& 'nnnonoo'
& 'nnnoono'
& 'nnnnooo'.
03 filler redefines valid-rpn-forms.
05 rpn-form occurs 4 pic x(7).
03 current-rpn-form pic x(7).
01 calculation-area.
03 osx pic 99.
03 operator-stack pic x(32).
03 oqx pic 99.
03 oqx1 pic 99.
03 output-queue pic x(32).
03 work-number pic s9999.
03 top-numerator pic s9999 sign leading separate.
03 top-denominator pic s9999 sign leading separate.
03 rsx pic 9.
03 result-stack occurs 8.
05 numerator pic s9999.
05 denominator pic s9999.
01 error-found pic x.
01 divide-by-zero-error pic x.
*> diagnostics
01 NL pic x value x'0A'.
01 NL-flag pic x value space.
01 display-level pic x value '0'.
01 loop-lim pic 9999 value 1500.
01 loop-count pic 9999 value 0.
01 message-area value spaces.
03 message-level pic x.
03 message-value pic x(128).
*> input and examples
01 instruction pic x(32) value spaces.
01 tsx pic 99.
01 tsx-lim pic 99 value 14.
01 test-statements.
03 filler pic x(32) value '1234;1 + 2 + 3 + 4'.
03 filler pic x(32) value '1234;1 * 2 * 3 * 4'.
03 filler pic x(32) value '1234;((1)) * (((2 * 3))) * 4'.
03 filler pic x(32) value '1234;((1)) * ((2 * 3))) * 4'.
03 filler pic x(32) value '1234;(1 + 2 + 3 + 4'.
03 filler pic x(32) value '1234;)1 + 2 + 3 + 4'.
03 filler pic x(32) value '1234;1 * * 2 * 3 * 4'.
03 filler pic x(32) value '5679;6 - (5 - 7) * 9'.
03 filler pic x(32) value '1268;((1 * (8 * 6) / 2))'.
03 filler pic x(32) value '4583;-5-3+(8*4)'.
03 filler pic x(32) value '4583;8 * 4 - 5 - 3'.
03 filler pic x(32) value '4583;8 * 4 - (5 + 3)'.
03 filler pic x(32) value '1223;1 * 3 / (2 - 2)'.
03 filler pic x(32) value '2468;(6 * 8) / 4 / 2'.
01 filler redefines test-statements.
03 filler occurs 14.
05 test-numbers pic x(4).
05 filler pic x.
05 test-statement pic x(27).
procedure division.
start-twentyfour.
display 'start twentyfour'
perform generate-numbers
display 'type h <enter> to see instructions'
accept instruction
perform until instruction = spaces or 'q'
evaluate true
when instruction = 'h'
perform display-instructions
when instruction = 'n'
perform generate-numbers
when instruction(1:1) = 'm'
move instruction(2:4) to number-definitions
perform validate-number
if divide-by-zero-error = space
and 24 * top-denominator = top-numerator
display number-definitions ' is solved by ' output-queue(1:oqx)
else
display number-definitions ' is not solvable'
end-if
when instruction = 'd0' or 'd1' or 'd2' or 'd3'
move instruction(2:1) to display-level
when instruction = 'e'
display 'examples:'
perform varying tsx from 1 by 1
until tsx > tsx-lim
move spaces to statement
move test-numbers(tsx) to number-definitions
move test-statement(tsx) to statement
perform evaluate-statement
perform show-result
end-perform
when other
move instruction to statement
perform evaluate-statement
perform show-result
end-evaluate
move spaces to instruction
display 'instruction? ' with no advancing
accept instruction
end-perform
display 'exit twentyfour'
stop run
.
generate-numbers.
perform with test after until divide-by-zero-error = space
and 24 * top-denominator = top-numerator
compute n(1) = random(seconds-past-midnight) * 10 *> seed
perform varying nd from 1 by 1 until nd > 4
compute n(nd) = random() * 10
perform until n(nd) <> 0
compute n(nd) = random() * 10
end-perform
end-perform
perform validate-number
end-perform
display NL 'numbers:' with no advancing
perform varying nd from 1 by 1 until nd > 4
display space n(nd) with no advancing
end-perform
display space
.
validate-number.
perform varying p4 from 1 by 1 until p4 > p4-lim
move permutation-4(p4) to current-permutation-4
perform varying od1 from 1 by 1 until od1 > od-lim
move operator-definitions(od1:1) to current-operators(1:1)
perform varying od2 from 1 by 1 until od2 > od-lim
move operator-definitions(od2:1) to current-operators(2:1)
perform varying odx from 1 by 1 until odx > od-lim
move operator-definitions(odx:1) to current-operators(3:1)
perform varying rpx from 1 by 1 until rpx > rpx-lim
move rpn-form(rpx) to current-rpn-form
move 0 to cpx co3
move spaces to output-queue
move 7 to oqx
perform varying oqx1 from 1 by 1 until oqx1 > oqx
if current-rpn-form(oqx1:1) = 'n'
add 1 to cpx
move current-permutation-4(cpx:1) to nd
move n(nd) to output-queue(oqx1:1)
else
add 1 to co3
move current-operators(co3:1) to output-queue(oqx1:1)
end-if
end-perform
end-perform
perform evaluate-rpn
if divide-by-zero-error = space
and 24 * top-denominator = top-numerator
exit paragraph
end-if
end-perform
end-perform
end-perform
end-perform
.
display-instructions.
display '1) Type h <enter> to repeat these instructions.'
display '2) The program will display four randomly-generated'
display ' single-digit numbers and will then prompt you to enter'
display ' an arithmetic expression followed by <enter> to sum'
display ' the given numbers to 24.'
display ' The four numbers may contain duplicates and the entered'
display ' expression must reference all the generated numbers and duplicates.'
display ' Warning: the program converts the entered infix expression'
display ' to a reverse polish notation (rpn) expression'
display ' which is then interpreted from RIGHT to LEFT.'
display ' So, for instance, 8*4 - 5 - 3 will not sum to 24.'
display '3) Type n <enter> to generate a new set of four numbers.'
display ' The program will ensure the generated numbers are solvable.'
display '4) Type m#### <enter> (e.g. m1234) to create a fixed set of numbers'
display ' for testing purposes.'
display ' The program will test the solvability of the entered numbers.'
display ' For example, m1234 is solvable and m9999 is not solvable.'
display '5) Type d0, d1, d2 or d3 followed by <enter> to display none or'
display ' increasingly detailed diagnostic information as the program evaluates'
display ' the entered expression.'
display '6) Type e <enter> to see a list of example expressions and results'
display '7) Type <enter> or q <enter> to exit the program'
.
show-result.
if error-found = 'y'
or divide-by-zero-error = 'y'
exit paragraph
end-if
display 'statement in RPN is' space output-queue
evaluate true
when top-numerator = 0
when top-denominator = 0
when 24 * top-denominator <> top-numerator
display 'result (' top-numerator '/' top-denominator ') is not 24'
when other
display 'result is 24'
end-evaluate
.
evaluate-statement.
compute l-lim = length(trim(statement))
display NL 'numbers:' space n(1) space n(2) space n(3) space n(4)
move number-definitions to number-use
display 'statement is' space statement
move 1 to l
move 0 to loop-count
move space to error-found
move 0 to osx oqx
move spaces to output-queue
move 1 to p
move 1 to nt
move 0 to s
perform increment-s
perform display-start-nonterminal
perform increment-p
*>===================================
*> interpret ebnf
*>===================================
perform until s = 0
or error-found = 'y'
evaluate true
when p-symbol(p) = 'n'
and p-definition(p) = 000 *> a variable
perform test-variable
if s-result(s) = 'S'
perform increment-l
end-if
perform increment-p
when p-symbol(p) = 'n'
and p-address(p) <> p-definition(p) *> nonterminal reference
move p to s-p(s)
move p-definition(p) to p
when p-symbol(p) = 'n'
and p-address(p) = p-definition(p) *> nonterminal definition
perform increment-s
perform display-start-nonterminal
perform increment-p
when p-symbol(p) = '=' *> nonterminal control
move p to s-start-control(s)
move p-matching(p) to s-end-control(s)
perform increment-p
when p-symbol(p) = ';' *> end nonterminal
perform display-end-control
perform display-end-nonterminal
perform decrement-s
if s > 0
evaluate true
when s-result(r) = 'S'
perform set-success
when s-result(r) = 'F'
perform set-failure
end-evaluate
move s-p(s) to p
perform increment-p
perform display-continue-nonterminal
end-if
when p-symbol(p) = '{' *> start repeat sequence
perform increment-s
perform display-start-control
move p to s-start-control(s)
move p-alternate(p) to s-alternate(s)
move p-matching(p) to s-end-control(s)
move 0 to s-count(s)
perform increment-p
when p-symbol(p) = '}' *> end repeat sequence
perform display-end-control
evaluate true
when s-result(s) = 'S' *> repeat the sequence
perform display-repeat-control
perform set-nothing
add 1 to s-repeat(s)
move s-start-control(s) to p
perform increment-p
when other
perform decrement-s
evaluate true
when s-result(r) = 'N'
and s-repeat(r) = 0 *> no result
perform increment-p
when s-result(r) = 'N'
and s-repeat(r) > 0 *> no result after success
perform set-success
perform increment-p
when other *> fail the sequence
perform increment-p
end-evaluate
end-evaluate
when p-symbol(p) = '(' *> start sequence
perform increment-s
perform display-start-control
move p to s-start-control(s)
move p-alternate(p) to s-alternate(s)
move p-matching(p) to s-end-control(s)
move 0 to s-count(s)
perform increment-p
when p-symbol(p) = ')' *> end sequence
perform display-end-control
perform decrement-s
evaluate true
when s-result(r) = 'S' *> success
perform set-success
perform increment-p
when s-result(r) = 'N' *> no result
perform set-failure
perform increment-p
when other *> fail the sequence
perform set-failure
perform increment-p
end-evaluate
when p-symbol(p) = '|' *> alternate
evaluate true
when s-result(s) = 'S' *> exit the sequence
perform display-skip-alternate
move s-end-control(s) to p
when other
perform display-take-alternate
move p-alternate(p) to s-alternate(s) *> the next alternate
perform increment-p
perform set-nothing
end-evaluate
when p-symbol(p) = 't' *> terminal
move p-definition(p) to t
move terminal-symbol-len(t) to t-len
perform display-terminal
evaluate true
when statement(l:t-len) = terminal-symbol(t)(1:t-len) *> successful match
perform set-success
perform display-recognize-terminal
perform process-token
move t-len to l-len
perform increment-l
perform increment-p
when s-alternate(s) <> 000 *> we are in an alternate sequence
move s-alternate(s) to p
when other *> fail the sequence
perform set-failure
move s-end-control(s) to p
end-evaluate
when other *> end control
perform display-control-failure *> shouldnt happen
end-evaluate
end-perform
evaluate true *> at end of evaluation
when error-found = 'y'
continue
when l <= l-lim *> not all tokens parsed
display 'error: invalid statement'
perform statement-error
when number-use <> spaces
display 'error: not all numbers were used: ' number-use
move 'y' to error-found
end-evaluate
.
increment-l.
evaluate true
when l > l-lim *> end of statement
continue
when other
add l-len to l
perform varying l from l by 1
until c(l) <> space
or l > l-lim
continue
end-perform
move 1 to l-len
if l > l-lim
perform end-tokens
end-if
end-evaluate
.
increment-p.
evaluate true
when p >= p-max
display 'at' space p ' parse overflow'
space 's=<' s space s-entry(s) '>'
move 'y' to error-found
when other
add 1 to p
perform display-statement
end-evaluate
.
increment-s.
evaluate true
when s >= s-max
display 'at' space p ' stack overflow '
space 's=<' s space s-entry(s) '>'
move 'y' to error-found
when other
move s to r
add 1 to s
initialize s-entry(s)
move 'N' to s-result(s)
move p to s-p(s)
move nt to s-nt(s)
end-evaluate
.
decrement-s.
if s > 0
move s to r
subtract 1 from s
if s > 0
move s-nt(s) to nt
end-if
end-if
.
set-failure.
move 'F' to s-result(s)
if s-count(s) > 0
display 'sequential parse failure'
perform statement-error
end-if
.
set-success.
move 'S' to s-result(s)
add 1 to s-count(s)
.
set-nothing.
move 'N' to s-result(s)
move 0 to s-count(s)
.
statement-error.
display statement
move spaces to statement
move '^ syntax error' to statement(l:)
display statement
move 'y' to error-found
.
*>=====================
*> twentyfour semantics
*>=====================
test-variable.
*> check validity
perform varying nd from 1 by 1 until nd > 4
or c(l) = n(nd)
continue
end-perform
*> check usage
perform varying nu from 1 by 1 until nu > 4
or c(l) = u(nu)
continue
end-perform
evaluate true
when l > l-lim
perform set-failure
when c9(l) not numeric
perform set-failure
when nd > 4
display 'invalid number'
perform statement-error
when nu > 4
display 'number already used'
perform statement-error
when other
move space to u(nu)
perform set-success
add 1 to oqx
move c(l) to output-queue(oqx:1)
end-evaluate
.
*> ==================================
*> Dijkstra Shunting-Yard Algorithm
*> to convert infix to rpn
*> ==================================
process-token.
evaluate true
when c(l) = '('
add 1 to osx
move c(l) to operator-stack(osx:1)
when c(l) = ')'
perform varying osx from osx by -1 until osx < 1
or operator-stack(osx:1) = '('
add 1 to oqx
move operator-stack(osx:1) to output-queue(oqx:1)
end-perform
if osx < 1
display 'parenthesis error'
perform statement-error
exit paragraph
end-if
subtract 1 from osx
when (c(l) = '+' or '-') and (operator-stack(osx:1) = '*' or '/')
*> lesser operator precedence
add 1 to oqx
move operator-stack(osx:1) to output-queue(oqx:1)
move c(l) to operator-stack(osx:1)
when other
*> greater operator precedence
add 1 to osx
move c(l) to operator-stack(osx:1)
end-evaluate
.
end-tokens.
*> 1) copy stacked operators to the output-queue
perform varying osx from osx by -1 until osx < 1
or operator-stack(osx:1) = '('
add 1 to oqx
move operator-stack(osx:1) to output-queue(oqx:1)
end-perform
if osx > 0
display 'parenthesis error'
perform statement-error
exit paragraph
end-if
*> 2) evaluate the rpn statement
perform evaluate-rpn
if divide-by-zero-error = 'y'
display 'divide by zero error'
end-if
.
evaluate-rpn.
move space to divide-by-zero-error
move 0 to rsx *> stack depth
perform varying oqx1 from 1 by 1 until oqx1 > oqx
if output-queue(oqx1:1) >= '1' and <= '9'
*> push current data onto the stack
add 1 to rsx
move top-numerator to numerator(rsx)
move top-denominator to denominator(rsx)
move output-queue(oqx1:1) to top-numerator
move 1 to top-denominator
else
*> apply the operation
evaluate true
when output-queue(oqx1:1) = '+'
compute top-numerator = top-numerator * denominator(rsx)
+ top-denominator * numerator(rsx)
compute top-denominator = top-denominator * denominator(rsx)
when output-queue(oqx1:1) = '-'
compute top-numerator = top-denominator * numerator(rsx)
- top-numerator * denominator(rsx)
compute top-denominator = top-denominator * denominator(rsx)
when output-queue(oqx1:1) = '*'
compute top-numerator = top-numerator * numerator(rsx)
compute top-denominator = top-denominator * denominator(rsx)
when output-queue(oqx1:1) = '/'
compute work-number = numerator(rsx) * top-denominator
compute top-denominator = denominator(rsx) * top-numerator
if top-denominator = 0
move 'y' to divide-by-zero-error
exit paragraph
end-if
move work-number to top-numerator
end-evaluate
*> pop the stack
subtract 1 from rsx
end-if
end-perform
.
*>====================
*> diagnostic displays
*>====================
display-start-nonterminal.
perform varying nt from nt-lim by -1 until nt < 1
or p-definition(p) = nonterminal-statement-number(nt)
continue
end-perform
if nt > 0
move '1' to NL-flag
string '1' indent(1:s + s) 'at ' s space p ' start ' trim(nonterminal-statement(nt))
into message-area perform display-message
move nt to s-nt(s)
end-if
.
display-continue-nonterminal.
move s-nt(s) to nt
string '1' indent(1:s + s) 'at ' s space p space p-symbol(p) ' continue ' trim(nonterminal-statement(nt)) ' with result ' s-result(s)
into message-area perform display-message
.
display-end-nonterminal.
move s-nt(s) to nt
move '2' to NL-flag
string '1' indent(1:s + s) 'at ' s space p ' end ' trim(nonterminal-statement(nt)) ' with result ' s-result(s)
into message-area perform display-message
.
display-start-control.
string '2' indent(1:s + s) 'at ' s space p ' start ' p-symbol(p) ' in ' trim(nonterminal-statement(nt))
into message-area perform display-message
.
display-repeat-control.
string '2' indent(1:s + s) 'at ' s space p ' repeat ' p-symbol(p) ' in ' trim(nonterminal-statement(nt)) ' with result ' s-result(s)
into message-area perform display-message
.
display-end-control.
string '2' indent(1:s + s) 'at ' s space p ' end ' p-symbol(p) ' in ' trim(nonterminal-statement(nt)) ' with result ' s-result(s)
into message-area perform display-message
.
display-take-alternate.
string '2' indent(1:s + s) 'at ' s space p ' take alternate' ' in ' trim(nonterminal-statement(nt))
into message-area perform display-message
.
display-skip-alternate.
string '2' indent(1:s + s) 'at ' s space p ' skip alternate' ' in ' trim(nonterminal-statement(nt))
into message-area perform display-message
.
display-terminal.
string '1' indent(1:s + s) 'at ' s space p
' compare ' statement(l:t-len) ' to ' terminal-symbol(t)(1:t-len)
' in ' trim(nonterminal-statement(nt))
into message-area perform display-message
.
display-recognize-terminal.
string '1' indent(1:s + s) 'at ' s space p ' recognize terminal: ' c(l) ' in ' trim(nonterminal-statement(nt))
into message-area perform display-message
.
display-recognize-variable.
string '1' indent(1:s + s) 'at ' s space p ' recognize digit: ' c(l) ' in ' trim(nonterminal-statement(nt))
into message-area perform display-message
.
display-statement.
compute p1 = p - s-start-control(s)
string '3' indent(1:s + s) 'at ' s space p
' statement: ' s-start-control(s) '/' p1
space p-symbol(p) space s-result(s)
' in ' trim(nonterminal-statement(nt))
into message-area perform display-message
.
display-control-failure.
display loop-count space indent(1:s + s) 'at' space p ' control failure' ' in ' trim(nonterminal-statement(nt))
display loop-count space indent(1:s + s) ' ' 'p=<' p p-entry(p) '>'
display loop-count space indent(1:s + s) ' ' 's=<' s space s-entry(s) '>'
display loop-count space indent(1:s + s) ' ' 'l=<' l space c(l)'>'
perform statement-error
.
display-message.
if display-level = 1
move space to NL-flag
end-if
evaluate true
when loop-count > loop-lim *> loop control
display 'display count exceeds ' loop-lim
stop run
when message-level <= display-level
evaluate true
when NL-flag = '1'
display NL loop-count space trim(message-value)
when NL-flag = '2'
display loop-count space trim(message-value) NL
when other
display loop-count space trim(message-value)
end-evaluate
end-evaluate
add 1 to loop-count
move spaces to message-area
move space to NL-flag
.
end program twentyfour.

View file

@ -0,0 +1,39 @@
defmodule Game24 do
def main do
IO.puts "24 Game"
play
end
defp play do
IO.puts "Generating 4 digits..."
digts = for _ <- 1..4, do: Enum.random(1..9)
IO.puts "Your digits\t#{inspect digts, char_lists: :as_lists}"
read_eval(digts)
play
end
defp read_eval(digits) do
exp = IO.gets("Your expression: ") |> String.strip
if exp in ["","q"], do: exit(:normal) # give up
case {correct_nums(exp, digits), eval(exp)} do
{:ok, x} when x==24 -> IO.puts "You Win!"
{:ok, x} -> IO.puts "You Lose with #{inspect x}!"
{err, _} -> IO.puts "The following numbers are wrong: #{inspect err, char_lists: :as_lists}"
end
end
defp correct_nums(exp, digits) do
nums = String.replace(exp, ~r/\D/, " ") |> String.split |> Enum.map(&String.to_integer &1)
if length(nums)==4 and (nums--digits)==[], do: :ok, else: nums
end
defp eval(exp) do
try do
Code.eval_string(exp) |> elem(0)
rescue
e -> Exception.message(e)
end
end
end
Game24.main

View file

@ -29,10 +29,9 @@ processGuess digits xs = calc xs >>= check
check x = Left (show (fromRational (x :: Rational)) ++ " is wrong")
-- A Reverse Polish Notation calculator with full error handling
calc = result []
where result [n] [] = Right n
result _ [] = Left "Too few operators"
result ns (x:xs) = simplify ns x >>= flip result xs
calc xs = foldM simplify [] xs >>= \ns -> (case ns of
[n] -> Right n
_ -> Left "Too few operators")
simplify (a:b:ns) s | isOp s = Right ((fromJust $ lookup s ops) b a : ns)
simplify _ s | isOp s = Left ("Too few values before " ++ s)

View file

@ -0,0 +1,84 @@
play24 := module()
export ModuleApply;
local cheating;
cheating := proc(input, digits)
local i, j, stringDigits;
use StringTools in
stringDigits := Implode([seq(convert(i, string), i in digits)]);
for i in digits do
for j in digits do
if Search(cat(convert(i, string), j), input) > 0 then
return true, ": Please don't combine digits to form another number."
end if;
end do;
end do;
for i in digits do
if CountCharacterOccurrences(input, convert(i, string)) < CountCharacterOccurrences(stringDigits, convert(i, string)) then
return true, ": Please use all digits.";
end if;
end do;
for i in digits do
if CountCharacterOccurrences(input, convert(i, string)) > CountCharacterOccurrences(stringDigits, convert(i, string)) then
return true, ": Please only use a digit once.";
end if;
end do;
for i in input do
try
if type(parse(i), numeric) and not member(parse(i), digits) then
return true, ": Please only use the digits you were given.";
end if;
catch:
end try;
end do;
return false, "";
end use;
end proc:
ModuleApply := proc()
local replay, digits, err, message, answer;
randomize():
replay := "":
while not replay = "END" do
if not replay = "YES" then
digits := [seq(rand(1..9)(), i = 1..4)]:
end if;
err := true:
while err do
message := "";
printf("Please make 24 from the digits: %a. Press enter for a new set of numbers or type END to quit\n", digits);
answer := StringTools[UpperCase](readline());
if not answer = "" and not answer = "END" then
try
if not type(parse(answer), numeric) then
error;
elif cheating(answer, digits)[1] then
message := cheating(answer, digits)[2];
error;
end if;
err := false;
catch:
printf("Invalid Input%s\n\n", message);
end try;
else
err := false;
end if;
end do:
if not answer = "" and not answer = "END" then
if parse(answer) = 24 then
printf("You win! Do you wish to play another game? (Press enter for a new set of numbers or END to quit.)\n");
replay := StringTools[UpperCase](readline());
else
printf("Your expression evaluated to %a. Try again!\n", parse(answer));
replay := "YES";
end if;
else
replay := answer;
end if;
printf("\n");
end do:
printf("GAME OVER\n");
end proc:
end module:
play24();

View file

@ -1,3 +1,5 @@
use MONKEY-SEE-NO-EVAL;
say "Here are your digits: ",
constant @digits = (1..9).roll(4)».Str;
@ -9,15 +11,16 @@ grammar Exp24 {
}
while my $exp = prompt "\n24? " {
if Exp24.parse: $exp {
say "You win :)";
last;
if try Exp24.parse: $exp {
say "You win :)";
last;
} else {
say pick 1,
'Sorry. Try again.' xx 20,
'Try harder.' xx 5,
'Nope. Not even close.' xx 2,
'Are you five or something?',
'Come on, you can do better than that.';
say (
'Sorry. Try again.' xx 20,
'Try harder.' xx 5,
'Nope. Not even close.' xx 2,
'Are you five or something?',
'Come on, you can do better than that.'
).flat.pick
}
}

View file

@ -64,4 +64,5 @@ def main():
if ans == 24:
print ("Thats right!")
print ("Thank you and goodbye")
main()
if __name__ == '__main__': main()

View file

@ -1,73 +1,68 @@
/*REXX program which allows a user to play the game of 24 (twenty-four). */
numeric digits 15 /*allow more leeway when computing #s. */
parse arg yyy /*get the optional arguments from C.L. */
yyy = space(yyy,0) /*remove extraneous blanks from YYY. */
parse var yyy start '-' fin /*get the START and FINish (maybe). */
fin = word(fin start,1) /*if no FINish specified, use START.*/
opers = '+-*/' /*define the legal arithmetic operators*/
ops = length(opers) /* ··· and the count of them (length). */
groupSymbols = '()[]{}' /*legal grouping symbols for this game.*/
indent = left('',30) /*used to indent display of solutions. */
Lpar = '(' /*a string to make the output prettier.*/
Rpar = ')' /*Ditto. [You can say that again.] */
digs = 123456789 /*numerals (digits) that can be used. */
show = 1 /*flag used show solutions (0 = not). */
do j=1 for ops /*define a version for fast execution. */
@.j=substr(opers,j,1) /*assign each operation to an array. */
end /*j*/
signal on syntax /*enable program to trap syntax errors.*/
if yyy\=='' then do /*if START (or FINish), then solve 'em.*/
sols=solve(start,fin) /*solve START ───► FINish. */
if sols <0 then exit 13 /*Was there a problem with input? */
if sols==0 then sols='No' /*Englishize the SOLS variable.*/
say; say sols 'unique solution's(sols) "found for" yyy
exit /*S [↑] does pluralizations. */
end
show=0 /*stop SOLVE from blabbing solutions.*/
/*REXX program supports a human to play the game of 24 (twenty-four) with error checking*/
numeric digits 15 /*allow more leeway when computing #s. */
parse arg yyy /*get the optional arguments from C.L. */
yyy = space(yyy, 0) /*remove extraneous blanks from YYY. */
parse var yyy start '-' fin /*get the START and FINish (maybe). */
fin = word(fin start, 1) /*if no FINish specified, use START.*/
ops = '+-*/' ; Lops = length(0ps) /*define the legal arithmetic operators*/
groupSym = '()[]{}' /*legal grouping symbols for this game.*/
indent = left('', 30) /*used to indent display of solutions. */
Lpar = '(' ; Rpar = ')' /*strings to make the output prettier.*/
digs = 123456789 /*numerals (digits) that can be used. */
show = 1 /*flag used show solutions (0 = not). */
do j=1 for Lops; @.j=substr(ops,j,1) /*define a version for fast execution. */
end /*j*/
signal on syntax /*enable program to trap syntax errors.*/
if yyy\=='' then do; sols=solve(start, fin) /*solve from START ───► FINish. */
if sols <0 then exit 13 /*Was there a problem with the input? */
if sols==0 then sols='No' /*Englishize the SOLS variable value*/
say; say sols 'unique solution's(sols) "found for" yyy
exit /*S [↑] does pluralizations. */
end
show=0 /*stop SOLVE from blabbing solutions.*/
do forever; rrrr=random(1111, 9999)
if pos(0, rrrr)\==0 then iterate /*if contains a zero, ignore it*/
if solve(rrrr)\==0 then leave /*if solved, then stop looking.*/
if pos(0, rrrr)\==0 then iterate /*if it contains a zero, then ignore it*/
if solve(rrrr) \==0 then leave /*if solved, then we can stop looking. */
end /*forever*/
show=1 /*enable SOLVE to display solutions. */
rrrr=sort(rrrr) /*sort four digits (for consistency). */
show=1 /*enable SOLVE to display solutions. */
rrrr=sort(rrrr); Lrrrr=length(rrrr) /*sort four digits (for consistency). */
$.=0
do j=1 for length(rrrr) /*digit count for each digit in RRRR. */
_=substr(rrrr, j, 1) /*pick off one of the digits in RRRR. */
$._=countDigs(rrrr, _) /*define the count for this digit. */
end /*j*/ /* [↑] counts duplicates twice, no harm*/
do j=1 for Lrrrr; _=substr(rrrr,j,1) /*digit count for each digit in RRRR. */
$._= countDigs(rrrr, _) /*define the count for this digit. */
end /*j*/ /* [↑] counts duplicates twice, no harm*/
prompt= 'Using the digits' rrrr", enter an expression that equals 24 (or QUIT):"
/* [↓] ITERATE needs a variable name.*/
do prompter=0; say; say prompt /*display blank line and the prompt (P)*/
pull y; y=space(y,0) /*get Y from CL, then remove all blanks*/
if abbrev('QUIT',y,1) then exit /*Does the user want to quit this game?*/
_v=verify(y, digs || opers || groupSymbols); a=substr(y, max(1,_v), 1)
if _v\==0 then do; call ger 'invalid character:' a; iterate; end
if pos('**',y) then do; call ger 'invalid ** operator'; iterate; end
if pos('//',y) then do; call ger 'invalid // operator'; iterate; end
yL=length(y)
if y=='' then do; call validate y; iterate; end
__ = copies('', 9) /*used for output highlighting. */
prompt= 'Using the digits ' rrrr", enter an expression that equals 24 (or QUIT):"
/* [↓] ITERATE needs a variable name.*/
do prompter=0; say; say __ prompt /*display blank line and the prompt (P)*/
pull y; y=space(y, 0) /*get Y from CL, then remove all blanks*/
if abbrev('QUIT', y, 1) then exit 0 /*Does the user want to quit this game?*/
_v=verify(y, digs || ops || groupSym); a=substr(y, max(1,_v), 1)
if _v\==0 then do; call ger "invalid character:" a; iterate; end
if pos('**', y) then do; call ger "invalid ** operator"; iterate; end
if pos('//', y) then do; call ger "invalid // operator"; iterate; end
Ly=length(y)
if y=='' then do; call validate y; iterate; end
do j=1 for yL-1; if \datatype(substr(y, j ,1), 'W') then iterate
if \datatype(substr(y, j+1,1), 'W') then iterate
do j=1 for Ly-1; if \datatype(substr(y, j , 1), 'W') then iterate
if \datatype(substr(y, j+1, 1), 'W') then iterate
call ger 'invalid use of "digit abuttal".'
iterate prompter
end /*j*/
yd=countDigs(y, digs) /*count of the digits 1──►9 (123456789)*/
if yd<4 then do; call ger 'not enough digits entered.'; iterate prompter; end
if yd>4 then do; call ger 'too many digits entered.' ; iterate prompter; end
yd=countDigs(y, digs) /*count of the digits 1──►9 (123456789)*/
if yd<4 then do; call ger 'not enough digits entered.'; iterate /*prompter*/; end
if yd>4 then do; call ger 'too many digits entered.' ; iterate /*prompter*/; end
do j=1 for 9; if $.j==0 then iterate
_d=countDigs(y, j); if $.j==_d then iterate
if _d<$.j then call ger 'not enough' j "digits, must be" $.j
else call ger 'too many' j "digits, must be" $.j
do j=1 for 9; if $.j==0 then iterate
_d=countDigs(y, j); if $.j==_d then iterate
if _d<$.j then call ger 'not enough' j "digits, must be" $.j
else call ger 'too many' j "digits, must be" $.j
iterate prompter
end /*j*/
y=translate(y, '()()', "[]{}")
interpret 'ans=' y; ans=ans/1; if ans==24 then leave prompter
say 'incorrect, ' y'='ans
interpret 'ans=' translate(y, '()()', "[]{}"); ans=ans/1
if ans==24 then leave prompter; say 'incorrect, ' y"="ans
end /*prompter*/
say; say center('', 79)
@ -75,84 +70,65 @@ say; say center('┌────────────────
say center(' congratulations ! ', 79)
say center(' ', 79)
say center('', 79)
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────one─liner subroutines─────────────────────*/
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
countDigs: arg ?; return length(?) - length(space(translate(?, , arg(2)), 0))
div: if arg(1)=0 then return 7e9; return arg(1) /*if ÷ by 0, fudge result*/
ger: say; say '***error!*** for argument:' y; say arg(1); say;errCode=1;return 0
s: if arg(1)==1 then return ''; return 's' /*simple pluralizer.*/
syntax: call ger 'illegal syntax in' y; exit
/*──────────────────────────────────SOLVE subroutine──────────────────────────*/
solve: parse arg ssss, ffff /*parse the argument passed to SOLVE. */
if ffff=='' then ffff=ssss /*create a FFFF if necessary. */
if \validate(ssss) then return -1 /*validate the SSSS field. */
if \validate(ffff) then return -1 /* " " FFFF " */
#=0 /*number of found solutions (so far). */
!.=0 /*a method to hold unique expressions. */
/*alternative: indent=copies(' ',30) */
div: if arg(1)=0 then return 7e9; return arg(1) /*÷ by 0? Fudge result*/
ger: say; say __ '***error*** for expression:' y; say __ arg(1); say; OK=0; return 0
s: if arg(1)==1 then return ''; return "s" /*a simple pluralizer.*/
syntax: call ger 'illegal syntax in' y; exit
/*──────────────────────────────────────────────────────────────────────────────────────*/
solve: parse arg ssss, ffff /*parse the argument passed to SOLVE. */
if ffff=='' then ffff=ssss /*create a FFFF if necessary. */
if \validate(ssss) then return -1 /*validate the SSSS field. */
if \validate(ffff) then return -1 /* " " FFFF " */
#=0 /*number of found solutions (so far). */
!.=0 /*a method to hold unique expressions. */
/*alternative: indent=copies(' ',30) */
do g=ssss to ffff /*process a (possible) range of values.*/
if pos(0, g)\==0 then iterate /*ignore values with zero in them. */
do g=ssss to ffff /*process a (possible) range of values.*/
if pos(0, g)\==0 then iterate /*ignore values with zero in them. */
do j=1 for 4; g.j=substr(g, j, 1) /*define a version for fast execution. */
end /*j*/
do j=1 for 4 /*define a version for fast execution. */
g.j=substr(g, j, 1) /*extract each digit of G into array.*/
end /*j*/
do i =1 for Lops /*insert an operator after 1st number. */
do j =1 for Lops /* " " " " 2nd " */
do k =1 for Lops /* " " " " 3rd " */
do m=0 to 3; L.= /*assume no left parenthesis (so far).*/
do n=m+1 to 4; L.m=Lpar; R.= /*match left paren with a right paren. */
if m==1 & n==2 then L.= /*special case of : (n) + ··· */
else if m\==0 then R.n=Rpar /*no (, no )*/
e= L.1 g.1 @.i L.2 g.2 @.j L.3 g.3 R.3 @.k g.4 R.4
e=space(e, 0) /*remove all blanks from the expression*/
yyyE=e /*keep old the version for the display.*/
/* [↓] change /(yyy) ═══► /div(yyy) */
if pos('/(', e)\==0 then e=changestr( "/(", e, '/div(' )
if !.e then iterate /*was this expression already used? */
!.e=1 /*mark this expression as being used. */
interpret 'x=' e /*have REXX do all the heavy lifting */
if x\=24 then iterate /*Is the result incorrect? Try again. */
#=#+1 /*bump number of found solutions. */
if show then say indent 'a solution:' translate(yyyE, '][', ")(")
end /*n*/ /* [↑] display a (single) solution. */
end /*m*/
end /*k*/
end /*j*/
end /*i*/
end /*g*/
do i =1 for ops /*insert an operator after 1st number. */
do j =1 for ops /*insert an operator after 2nd number. */
do k =1 for ops /*insert an operator after 2nd number. */
do m=0 to 3; L.= /*assume no left parenthesis so far. */
do n=m+1 to 4 /*match left paren with a right paren. */
L.m=Lpar /*define a left paren, m=0 means ignore*/
R.= /*un-define all right parenthesis. */
if m==1 & n==2 then L.= /*special case of : (n) + ··· */
else if m\==0 then R.n=Rpar /*no (, no )*/
e = L.1 g.1 @.i L.2 g.2 @.j L.3 g.3 R.3 @.k g.4 R.4
e=space(e, 0) /*remove all blanks from the expression*/
/* [↓] change expression: */
/* /(yyy) ═══► /div(yyy) */
/*Enables to check for division by zero*/
yyyE=e /*keep old the version for the display.*/
if pos('/(', e)\==0 then e=changestr( '/(', e, "/div(" )
/* [↓] INTERPRET stresses REXX's groin,*/
/* so try to avoid repeated lifting.*/
if !.e then iterate /*was this expression already used? */
!.e=1 /*mark this expression as being used. */
interpret 'x=' e /*have REXX do all the heavy lifting */
x=x/1 /*remove any trailing decimal point. */
if x\==24 then iterate /*Is the result incorrect? Try again. */
#=#+1 /*bump number of found solutions. */
_=translate(yyyE, '][', ")(") /*display [], not (). */
if show then say indent 'a solution:' _
end /*n*/ /* [↑] show a solution.*/
end /*m*/
end /*k*/
end /*j*/
end /*i*/
end /*g*/
return #
/*──────────────────────────────────SORT subroutine───────────────────────────*/
sort: procedure; arg nnnn; L=length(nnnn)
do i=1 for L /*build an array of digits from NNNN. */
s.i=substr(nnnn, i, 1) /*this enables SORT to sort an array. */
end /*i*/
do j=1 for L; _=s.j
do k=j+1 to L
if s.k<_ then parse value s.j s.k with s.k s.j
end /*k*/
end /*j*/
return s.1 || s.2 || s.3 || s.4
/*──────────────────────────────────VALIDATE subroutine───────────────────────*/
validate: parse arg y; errCode=0; _v=verify(y,digs)
select
when y=='' then call ger 'no digits entered.'
when length(y)<4 then call ger 'not enough digits entered, must be four.'
when length(y)>4 then call ger 'too many digits entered, must be four.'
when pos(0,y)\==0 then call ger "can't use the digit 0 (zero)."
when _v\==0 then call ger 'illegal character: ' substr(y,_v,1)
otherwise nop
end /*select*/
return \errCode
return #
/*──────────────────────────────────────────────────────────────────────────────────────*/
sort: procedure; parse arg #; L=length(#); !.= /*this is a modified bin sort.*/
do d=1 for L; _=substr(#, d, 1); !.d=!.d || _; end /*d*/
return space(!.0 !.1 !.2 !.3 !.4 !.5 !.6 !.7 !.8 !.9, 0) /*reconstitute the #.*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
validate: parse arg y; OK=1; _v=verify(y,digs); DE='digits entered, there must be four.'
select
when y=='' then call ger "no" DE
when length(y)<4 then call ger "not enough" DE
when length(y)>4 then call ger "too many" DE
when pos(0,y)\==0 then call ger "can't use the digit 0 (zero)."
when _v\==0 then call ger "illegal character: " substr(y, _v, 1)
otherwise nop
end /*select*/
return OK

View file

@ -1,16 +1,14 @@
def validate(guess, nums)
name, error =
{
invalid_character: ->(str){ !str.scan(%r{[^\d\s()+*/-]}).empty? },
wrong_number: ->(str){ str.scan(/\d/).map(&:to_i).sort != nums.sort },
multi_digit_number: ->(str){ str.match(/\d\d/) }
}
.find {|name, validator| validator[guess] }
error ? puts("Invalid input of a(n) #{name.to_s.tr('_',' ')}!") : true
end
class Guess < String
def self.play
nums = Array.new(4){rand(1..9)}
loop do
result = get(nums).evaluate!
break if result == 24.0
puts "Try again! That gives #{result}!"
end
puts "You win!"
end
def self.get(nums)
loop do
print "\nEnter a guess using #{nums}: "
@ -19,24 +17,24 @@ class Guess < String
end
end
def self.validate(guess, nums)
name, error =
{
invalid_character: ->(str){ !str.scan(%r{[^\d\s()+*/-]}).empty? },
wrong_number: ->(str){ str.scan(/\d/).map(&:to_i).sort != nums.sort },
multi_digit_number: ->(str){ str.match(/\d\d/) }
}
.find {|name, validator| validator[guess] }
error ? puts("Invalid input of a(n) #{name.to_s.tr('_',' ')}!") : true
end
def evaluate!
as_rat = gsub(/(\d)/, 'Rational(\1,1)')
begin
eval "(#{as_rat}).to_f"
rescue SyntaxError
"[syntax error]"
end
as_rat = gsub(/(\d)/, '\1r') # r : Rational suffix
eval "(#{as_rat}).to_f"
rescue SyntaxError
"[syntax error]"
end
end
def play
nums = Array.new(4){rand(1..9)}
loop do
result = Guess.get(nums).evaluate!
break if result == 24.0
puts "Try again! That gives #{result}!"
end
puts "You win!"
end
play
Guess.play

View file

@ -0,0 +1,102 @@
use std::io::{self,BufRead};
extern crate rand;
use rand::Rng;
fn op_type(x: char) -> i32{
match x {
'-' | '+' => return 1,
'/' | '*' => return 2,
'(' | ')' => return -1,
_ => return 0,
}
}
fn to_rpn(input: &mut String){
let mut rpn_string : String = String::new();
let mut rpn_stack : String = String::new();
let mut last_token = '#';
for token in input.chars(){
if token.is_digit(10) {
rpn_string.push(token);
}
else if op_type(token) == 0 {
continue;
}
else if op_type(token) > op_type(last_token) || token == '(' {
rpn_stack.push(token);
last_token=token;
}
else {
while let Some(top) = rpn_stack.pop() {
if top=='(' {
break;
}
rpn_string.push(top);
}
if token != ')'{
rpn_stack.push(token);
}
}
}
while let Some(top) = rpn_stack.pop() {
rpn_string.push(top);
}
println!("you formula results in {}", rpn_string);
*input=rpn_string;
}
fn calculate(input: &String, list : &mut [u32;4]) -> f32{
let mut stack : Vec<f32> = Vec::new();
let mut accumulator : f32 = 0.0;
for token in input.chars(){
if token.is_digit(10) {
let test = token.to_digit(10).unwrap() as u32;
match list.iter().position(|&x| x == test){
Some(idx) => list[idx]=10 ,
_ => println!(" invalid digit: {} ",test),
}
stack.push(accumulator);
accumulator = test as f32;
}else{
let a = stack.pop().unwrap();
accumulator = match token {
'-' => a-accumulator,
'+' => a+accumulator,
'/' => a/accumulator,
'*' => a*accumulator,
_ => {accumulator},//NOP
};
}
}
println!("you formula results in {}",accumulator);
accumulator
}
fn main() {
let mut rng = rand::thread_rng();
let mut list :[u32;4]=[rng.gen::<u32>()%10,rng.gen::<u32>()%10,rng.gen::<u32>()%10,rng.gen::<u32>()%10];
println!("form 24 with using + - / * {:?}",list);
//get user input
let mut input = String::new();
io::stdin().read_line(&mut input).unwrap();
//convert to rpn
to_rpn(&mut input);
let result = calculate(&input, &mut list);
if list.iter().any(|&list| list !=10){
println!("and you used all numbers");
match result {
24.0 => println!("you won"),
_ => println!("but your formulla doesn't result in 24"),
}
}else{
println!("you didn't use all the numbers");
}
}

View file

@ -0,0 +1,52 @@
10 LET n$=""
20 RANDOMIZE
30 FOR i=1 TO 4
40 LET n$=n$+STR$ (INT (RND*9)+1)
50 NEXT i
60 LET i$="": LET f$="": LET p$=""
70 CLS
80 PRINT "24 game"
90 PRINT "Allowed characters:"
100 LET i$=n$+"+-*/()"
110 PRINT AT 4,0;
120 FOR i=1 TO 10
130 PRINT i$(i);" ";
140 NEXT i
150 PRINT "(0 to end)"
160 INPUT "Enter the formula";f$
170 IF f$="0" THEN STOP
180 PRINT AT 6,0;f$;" = ";
190 FOR i=1 TO LEN f$
200 LET c$=f$(i)
210 IF c$=" " THEN LET f$(i)="": GO TO 250
220 IF c$="+" OR c$="-" OR c$="*" OR c$="/" THEN LET p$=p$+"o": GO TO 250
230 IF c$="(" OR c$=")" THEN LET p$=p$+c$: GO TO 250
240 LET p$=p$+"n"
250 NEXT i
260 RESTORE
270 FOR i=1 TO 11
280 READ t$
290 IF t$=p$ THEN LET i=11
300 NEXT i
310 IF t$<>p$ THEN PRINT INVERSE 1;"Bad construction!": BEEP 1,.1: PAUSE 0: GO TO 60
320 FOR i=1 TO LEN f$
330 FOR j=1 TO 10
340 IF (f$(i)=i$(j)) AND f$(i)>"0" AND f$(i)<="9" THEN LET i$(j)=" "
350 NEXT j
360 NEXT i
370 IF i$( TO 4)<>" " THEN PRINT FLASH 1;"Invalid arguments!": BEEP 1,.01: PAUSE 0: GO TO 60
380 LET r=VAL f$
390 PRINT r;" ";
400 IF r<>24 THEN PRINT FLASH 1;"Wrong!": BEEP 1,1: PAUSE 0: GO TO 60
410 PRINT FLASH 1;"Correct!": PAUSE 0: GO TO 10
420 DATA "nononon"
430 DATA "(non)onon"
440 DATA "nono(non)"
450 DATA "no(no(non))"
460 DATA "((non)on)on"
470 DATA "no(non)on"
480 DATA "(non)o(non)"
485 DATA "no((non)on)"
490 DATA "(nonon)on"
495 DATA "(no(non))on"
500 DATA "no(nonon)"

View file

@ -1,14 +1,17 @@
This task is a variation of the [[wp:The Nine Billion Names of God#Plot_summary|short story by Arthur C. Clarke]].
(Solvers should be aware of the consequences of completing this task.)
In detail, to specify what is meant by a “name”:
:The integer 1 has 1 name “1”.
:The integer 2 has 2 names “1+1”, and “2”.
:The integer 3 has 3 names “1+1+1”, “2+1”, and “3”.
:The integer 4 has 5 names “1+1+1+1”, “2+1+1”, “2+2”, “3+1”, “4”.
:The integer 5 has 7 names “1+1+1+1+1”, “2+1+1+1”, “2+2+1”, “3+1+1”, “3+2”, “4+1”, “5”.
In detail, to specify what is meant by a &nbsp; “name”:
:The integer 1 has 1 name &nbsp; &nbsp; “1”.
:The integer 2 has 2 names &nbsp; “1+1”, &nbsp; and &nbsp; “2”.
:The integer 3 has 3 names &nbsp; “1+1+1”, &nbsp; “2+1”, &nbsp; and &nbsp; “3”.
:The integer 4 has 5 names &nbsp; “1+1+1+1”, &nbsp; “2+1+1”, &nbsp; “2+2”, &nbsp; “3+1”, &nbsp; “4”.
:The integer 5 has 7 names &nbsp; “1+1+1+1+1”, &nbsp; “2+1+1+1”, &nbsp; “2+2+1”, &nbsp; “3+1+1”, &nbsp; “3+2”, &nbsp; “4+1”, &nbsp; “5”.
;Task
The task is to display the first 25 rows of a number triangle which begins:
Display the first 25 rows of a number triangle which begins:
<pre>
1
1 1
@ -18,11 +21,18 @@ The task is to display the first 25 rows of a number triangle which begins:
1 3 3 2 1 1
</pre>
Where row <math>n</math> corresponds to integer <math>n</math>, and each column <math>C</math> in row <math>m</math> from left to right corresponds to the number of names begining with <math>C</math>.
Where row &nbsp; <math>n</math> &nbsp; corresponds to integer &nbsp; <math>n</math>, &nbsp; and each column &nbsp; <math>C</math> &nbsp; in row &nbsp; <math>m</math> &nbsp; from left to right corresponds to the number of names beginning with &nbsp; <math>C</math>.
A function &nbsp; <math>G(n)</math> &nbsp; should return the sum of the &nbsp; <math>n</math>-th &nbsp; row.
Demonstrate this function by displaying: &nbsp; <math>G(23)</math>, &nbsp; <math>G(123)</math>, &nbsp; <math>G(1234)</math>, &nbsp; and &nbsp; <math>G(12345)</math>.
Optionally note that the sum of the &nbsp; <math>n</math>-th &nbsp; row &nbsp; <math>P(n)</math> &nbsp; is the &nbsp; [http://mathworld.wolfram.com/PartitionFunctionP.html &nbsp; integer partition function].
Demonstrate this is equivalent to &nbsp; <math>G(n)</math> &nbsp; by displaying: &nbsp; <math>P(23)</math>, &nbsp; <math>P(123)</math>, &nbsp; <math>P(1234)</math>, &nbsp; and &nbsp; <math>P(12345)</math>.
A function <math>G(n)</math> should return the sum of the <math>n</math>-th row. Demonstrate this function by displaying: <math>G(23)</math>, <math>G(123)</math>, <math>G(1234)</math>, and <math>G(12345)</math>.
Optionally note that the sum of the <math>n</math>-th row <math>P(n)</math> is the [http://mathworld.wolfram.com/PartitionFunctionP.html integer partition function]. Demonstrate this is equivalent to <math>G(n)</math> by displaying: <math>P(23)</math>, <math>P(123)</math>, <math>P(1234)</math>, and <math>P(12345)</math>.
;Extra credit
If your environment is able, plot <math>P(n)</math> against <math>n</math> for <math>n=1\ldots 999</math>.
If your environment is able, plot &nbsp; <math>P(n)</math> &nbsp; against &nbsp; <math>n</math> &nbsp; for &nbsp; <math>n=1\ldots 999</math>.
<br><br>

View file

@ -0,0 +1,12 @@
defmodule God do
def g(n,g) when g == 1 or n < g, do: 1
def g(n,g) do
Enum.reduce(2..g, 1, fn q,res ->
res + (if q > n-g, do: 0, else: g(n-g,q))
end)
end
end
Enum.each(1..25, fn n ->
IO.puts Enum.map(1..n, fn g -> "#{God.g(n,g)} " end)
end)

View file

@ -0,0 +1,33 @@
PrintArray(List([1 .. 25], n -> List([1 .. n], k -> NrPartitions(n, k))));
[ [ 1 ],
[ 1, 1 ],
[ 1, 1, 1 ],
[ 1, 2, 1, 1 ],
[ 1, 2, 2, 1, 1 ],
[ 1, 3, 3, 2, 1, 1 ],
[ 1, 3, 4, 3, 2, 1, 1 ],
[ 1, 4, 5, 5, 3, 2, 1, 1 ],
[ 1, 4, 7, 6, 5, 3, 2, 1, 1 ],
[ 1, 5, 8, 9, 7, 5, 3, 2, 1, 1 ],
[ 1, 5, 10, 11, 10, 7, 5, 3, 2, 1, 1 ],
[ 1, 6, 12, 15, 13, 11, 7, 5, 3, 2, 1, 1 ],
[ 1, 6, 14, 18, 18, 14, 11, 7, 5, 3, 2, 1, 1 ],
[ 1, 7, 16, 23, 23, 20, 15, 11, 7, 5, 3, 2, 1, 1 ],
[ 1, 7, 19, 27, 30, 26, 21, 15, 11, 7, 5, 3, 2, 1, 1 ],
[ 1, 8, 21, 34, 37, 35, 28, 22, 15, 11, 7, 5, 3, 2, 1, 1 ],
[ 1, 8, 24, 39, 47, 44, 38, 29, 22, 15, 11, 7, 5, 3, 2, 1, 1 ],
[ 1, 9, 27, 47, 57, 58, 49, 40, 30, 22, 15, 11, 7, 5, 3, 2, 1, 1 ],
[ 1, 9, 30, 54, 70, 71, 65, 52, 41, 30, 22, 15, 11, 7, 5, 3, 2, 1, 1 ],
[ 1, 10, 33, 64, 84, 90, 82, 70, 54, 42, 30, 22, 15, 11, 7, 5, 3, 2, 1, 1 ],
[ 1, 10, 37, 72, 101, 110, 105, 89, 73, 55, 42, 30, 22, 15, 11, 7, 5, 3, 2, 1, 1 ],
[ 1, 11, 40, 84, 119, 136, 131, 116, 94, 75, 56, 42, 30, 22, 15, 11, 7, 5, 3, 2, 1, 1 ],
[ 1, 11, 44, 94, 141, 163, 164, 146, 123, 97, 76, 56, 42, 30, 22, 15, 11, 7, 5, 3, 2, 1, 1 ],
[ 1, 12, 48, 108, 164, 199, 201, 186, 157, 128, 99, 77, 56, 42, 30, 22, 15, 11, 7, 5, 3, 2, 1, 1 ],
[ 1, 12, 52, 120, 192, 235, 248, 230, 201, 164, 131, 100, 77, 56, 42, 30, 22, 15, 11, 7, 5, 3, 2, 1, 1 ] ]
List([23, 123, 1234, 12345], NrPartitions);
[ 1255, 2552338241, 156978797223733228787865722354959930,
69420357953926116819562977205209384460667673094671463620270321700806074195845953959951425306140971942519870679768681736 ]

View file

@ -1,11 +1,11 @@
rowSums=: 3 :0"0
z=. (y+1){. 1x
for_ks. <\1+i.y do.
n=.{: k=.>ks
r=.#c=. ({.~* i._1:)(n,0.5 _1.5) p. k
s=.#d=.({.~* i._1:)c-r{.k
'v i'=.|: \:~(c,d),. r ,&({.&k) s
a=. +/(n{z),(_1^1x+2|i) * v{z
z=. a n}z
end.
z=. (y+1){. 1x
for_ks. <\1+i.y do.
n=.{: k=.>ks
r=.#c=. ({.~* i._1:)(n,0.5 _1.5) p. k
s=.#d=.({.~* i._1:)c-r{.k
'v i'=.|: \:~(c,d),. r ,&({.&k) s
a=. +/(n{z),(_1^1x+2|i) * v{z
z=. a n}z
end.
)

View file

@ -0,0 +1,41 @@
import java.math.BigInteger;
import java.util.*;
import static java.util.Arrays.asList;
import static java.util.stream.Collectors.toList;
import static java.util.stream.IntStream.range;
import static java.lang.Math.min;
public class Test {
static List<BigInteger> cumu(int n) {
List<List<BigInteger>> cache = new ArrayList<>();
cache.add(asList(BigInteger.ONE));
for (int L = cache.size(); L < n + 1; L++) {
List<BigInteger> r = new ArrayList<>();
r.add(BigInteger.ZERO);
for (int x = 1; x < L + 1; x++)
r.add(r.get(r.size() - 1).add(cache.get(L - x).get(min(x, L - x))));
cache.add(r);
}
return cache.get(n);
}
static List<BigInteger> row(int n) {
List<BigInteger> r = cumu(n);
return range(0, n).mapToObj(i -> r.get(i + 1).subtract(r.get(i)))
.collect(toList());
}
public static void main(String[] args) {
System.out.println("Rows:");
for (int x = 1; x < 11; x++)
System.out.printf("%2d: %s%n", x, row(x));
System.out.println("\nSums:");
for (int x : new int[]{23, 123, 1234}) {
List<BigInteger> c = cumu(x);
System.out.printf("%s %s%n", x, c.get(c.size() - 1));
}
}
}

View file

@ -0,0 +1,29 @@
fun namesOfGod(n: Int): List<BigInteger> {
val cache = ArrayList<List<BigInteger>>()
cache.add(asList(BigInteger.ONE))
(cache.size..n).forEach { l ->
val r = ArrayList<BigInteger>()
r.add(BigInteger.ZERO)
(1..l).forEach { x ->
r.add(r[r.size - 1] + cache[l - x][min(x, l - x)])
}
cache.add(r)
}
return cache[n]
}
fun row(n: Int) = namesOfGod(n).let { r -> (0..n-1).map { r[it + 1] - r[it] } }
println("Rows:")
(1..25).forEach {
System.out.printf("%2d: %s%n", it, row(it))
}
println("\nSums:")
intArrayOf(23, 123, 1234, 1234).forEach {
val c = namesOfGod(it)
System.out.printf("%s %s%n", it, c[c.size - 1])
}

View file

@ -0,0 +1,5 @@
row(n)=my(v=vector(n)); forpart(i=n,v[i[#i]]++); v;
show(n)=for(k=1,n,print(row(k)));
show(25)
apply(numbpart, [23,123,1234,12345])
plot(x=1,999.9, numbpart(x\1))

View file

@ -1,4 +1,4 @@
my @todo = [1];
my @todo = $[1];
my @sums = 0;
sub nextrow($n) {
for +@todo .. $n -> $l {
@ -24,6 +24,6 @@ say .fmt('%2d'), ": ", nextrow($_)[] for 1..10;
say "\nsums:";
for 23, 123, 1234, 10000 {
for 23, 123, 1234, 12345 {
say $_, "\t", [+] nextrow($_)[];
}

View file

@ -1,52 +1,52 @@
/*REXX program generates & shows a number triangle for partitions of a number.*/
numeric digits 400 /*be able to handle larger numbers. */
parse arg N .; if N=='' then N=25 /*N specified? Then use the default. */
/*REXX program generates and displays a number triangle for partitions of a number. */
numeric digits 400 /*be able to handle larger numbers. */
parse arg N .; if N=='' then N=25 /*N specified? Then use the default. */
@.=0; @.0=1; aN=abs(N)
if N==N+0 then say ' G('aN"):" G(N) /*just for well formed numbers.*/
say 'partitions('aN"):" partitions(aN) /*do it the easy way*/
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────G subroutine──────────────────────────────*/
G: procedure; parse arg nn; !.=0; mx=1; aN=abs(nn); build=nn>0
!.4.2=2; do j=1 for aN%2; !.j.j=1; end /*j*/ /*gen shortcuts.*/
if N==N+0 then say ' G('aN"):" G(N) /*just do this for well formed numbers.*/
say 'partitions('aN"):" partitions(aN) /*do it the easy way.*/
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
G: procedure; parse arg nn; !.=0; mx=1; aN=abs(nn); build=nn>0
!.4.2=2; do j=1 for aN%2; !.j.j=1; end /*j*/ /*generate some shortcuts.*/
do t=1 for 1+build; #.=1 /*gen triangle once or twice ···*/
do r=1 for aN; #.2=r%2 /*#.2 is a shortcut calculation.*/
do c=3 to r-2; #.c=gen#(r,c); end /*c*/
L=length(mx); p=0; __= /*__ will be a row (line) of triangle.*/
do cc=1 for r /*only sum the last row of numbers. */
p=p+#.cc /*add the last row of the triangle. */
if \build then iterate /*should we skip building the triangle?*/
mx=max(mx,#.cc) /*used to build the symmetric numbers. */
__=__ right(#.cc,L) /*construct a row (or line) of triangle*/
end /*cc*/
if t==1 then iterate /*Is this the 1st time through? No show*/
say center(strip(__), 2+(aN-1)*(length(mx)+1))
end /*r*/ /* [↑] center the row of the triangle.*/
end /*t*/
return p /*return with the generated number. */
/*──────────────────────────────────GEN# subroutine───────────────────────────*/
gen#: procedure expose !.; parse arg x,y /*obtain X and Y arguments. */
if !.x.y\==0 then return !.x.y /*was number generated before?*/
if y>x%2 then do; nx=x+1-2*(y-x%2)-(x//2==0); ny=nx%2; !.x.y=!.nx.ny
return !.x.y /*return the calculated number*/
end /* [↑] right half of triangle*/
$=1 /* [↓] left " " " */
do q=2 for y-1; xy=x-y; if q>xy then iterate
if q==2 then $=$+xy%2
else if q==xy-1 then $=$+1
else $=$+gen#(xy,q) /*recurse.*/
end /*q*/
!.x.y=$; return $ /*use memoization; return with number.*/
/*──────────────────────────────────PARTITIONS subroutine─────────────────────*/
partitions: procedure expose @.; parse arg n; if @.n\==0 then return @.n /*◄─┐*/
$=0 /*Already known? Then return value►───┘*/
do k=1 for n; _=n-(k*3-1)*k%2; if _<0 then leave
if @._==0 then x=partitions(_) /* [◄] recursive call.*/
else x=@._ /*value already known. */
_=_-k; if _<0 then y=0 /*recursive call ►────┐*/
else if @._==0 then y=partitions(_) /*◄──┘*/
else y=@._
if k//2 then $=$+x+y /*utilize this method if K is odd. */
else $=$2x-y /* " " " " " " even. */
end /*k*/ /* [↑] Euler's recursive function. */
@.n=$; return $ /*use memoization; return with number.*/
do t=1 for 1+build; #.=1 /*generate triangle once or twice. */
do r=1 for aN; #.2=r%2 /*#.2 is a shortcut calculation. */
do c=3 to r-2; #.c=gen#(r,c); end /*c*/
L=length(mx); p=0; __= /*__ will be a row of the triangle*/
do cc=1 for r /*only sum the last row of numbers.*/
p=p+#.cc /*add the last row of the triangle.*/
if \build then iterate /*should we skip building triangle?*/
mx=max(mx, #.cc) /*used to build the symmetric #s. */
__=__ right(#.cc, L) /*construct a row of the triangle. */
end /*cc*/
if t==1 then iterate /*Is this 1st time through? No show*/
say center(strip(__), 2+(aN-1)*(length(mx)+1))
end /*r*/ /* [↑] center row of the triangle.*/
end /*t*/
return p /*return with the generated number.*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
gen#: procedure expose !.; parse arg x,y /*obtain the X and Y arguments.*/
if !.x.y\==0 then return !.x.y /*was number generated before ? */
if y>x%2 then do; nx=x+1-2*(y-x%2)-(x//2==0); ny=nx%2; !.x.y=!.nx.ny
return !.x.y /*return the calculated number. */
end /* [↑] right half of triangle. */
$=1 /* [↓] left " " " */
do q=2 for y-1; xy=x-y; if q>xy then iterate
if q==2 then $=$+xy%2
else if q==xy-1 then $=$+1
else $=$+gen#(xy,q) /*recurse.*/
end /*q*/
!.x.y=$; return $ /*use memoization; return with #.*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
partitions: procedure expose @.; parse arg n; if @.n\==0 then return @.n /* ◄────────┐ */
$=0 /*Already known? Return ►───┘ */
do k=1 for n; _=n-(k*3-1)*k%2; if _<0 then leave
if @._==0 then x=partitions(_) /* [◄] recursive call.*/
else x=@._ /*value already known. */
_=_-k; if _<0 then y=0 /*recursive call ►────┐*/
else if @._==0 then y=partitions(_) /*◄──┘*/
else y=@._
if k//2 then $=$+x+y /*use this method if K is odd. */
else $=$-x-y /* " " " " " " even.*/
end /*k*/ /* [↑] Euler's recursive func.*/
@.n=$; return $ /*use memoization; return #. */

View file

@ -0,0 +1,45 @@
extern crate num;
use std::cmp;
use num::bigint::BigUint;
fn cumu(n: usize, cache: &mut Vec<Vec<BigUint>>) {
for l in cache.len()..n+1 {
let mut r = vec![BigUint::from(0u32)];
for x in 1..l+1 {
let prev = r[r.len() - 1].clone();
r.push(prev + cache[l-x][cmp::min(x, l-x)].clone());
}
cache.push(r);
}
}
fn row(n: usize, cache: &mut Vec<Vec<BigUint>>) -> Vec<BigUint> {
cumu(n, cache);
let r = &cache[n];
let mut v: Vec<BigUint> = Vec::new();
for i in 0..n {
v.push(&r[i+1] - &r[i]);
}
v
}
fn main() {
let mut cache = vec![vec![BigUint::from(1u32)]];
println!("rows:");
for x in 1..26 {
let v: Vec<String> = row(x, &mut cache).iter().map(|e| e.to_string()).collect();
let s: String = v.join(" ");
println!("{}: {}", x, s);
}
println!("sums:");
for x in vec![23, 123, 1234, 12345] {
cumu(x, &mut cache);
let v = &cache[x];
let s = v[v.len() - 1].to_string();
println!("{}: {}", x, s);
}
}

View file

@ -1,25 +1,29 @@
'''The beersong'''<br>
In this puzzle, write code to print out
the entire "99 bottles of beer on the wall" song.
;Task:
Display the complete lyrics for the song: &nbsp; &nbsp; '''99 bottles of beer on the wall'''.
For those who do not know the song, the lyrics follow this form:
X bottles of beer on the wall
X bottles of beer
Take one down, pass it around
X-1 bottles of beer on the wall
X-1 bottles of beer on the wall
...
Take one down, pass it around
0 bottles of beer on the wall
;The beersong:
The lyrics follow this form:
X bottles of beer on the wall
X bottles of beer
Take one down, pass it around
X-1 bottles of beer on the wall
X-1 bottles of beer on the wall
...
Take one down, pass it around
0 bottles of beer on the wall
Where X and X-1 are replaced by numbers of course.
Grammatical support for "1 bottle of beer" is optional.
As with any puzzle, try to do it in as creative/concise/comical a way
as possible (simple, obvious solutions allowed, too).
;See also:
* http://99-bottles-of-beer.net/
* [[:Category:99_Bottles_of_Beer]]
* [[:Category:Programming language families]]
<hr>
* [https://en.wikipedia.org/wiki/99_Bottles_of_Beer Wikipedia 99 bottles of beer]
<br><br>

View file

@ -0,0 +1,91 @@
-- BRIEF
on run
intercalate("\n\n", ¬
map(recitation, range(99, 0)))
end run
-- DECLARATIVE
script recitation
property coordinates : " on the wall"
property redistribution : "Take one down, pass it around"
property resort : "Better go to the store to buy some more"
property unit : "bottle"
-- Int -> String
on lambda(n)
if n > 0 then
set reserve to resourceDescriptor(n)
set residue to resourceDescriptor(n - 1)
intercalate(linefeed, ¬
{reserve & coordinates, reserve, ¬
redistribution, residue & coordinates})
else
resort
end if
end lambda
-- resourceDescriptor :: Int -> String
on resourceDescriptor(n)
if n 1 then
(n as string) & space & unit & "s"
else
"1 " & unit
end if
end resourceDescriptor
end script
-- DYSFUNCTIONAL
-- map :: (a -> b) -> [a] -> [b]
on map(f, xs)
tell mReturn(f)
set lng to length of xs
set lst to {}
repeat with i from 1 to lng
set end of lst to lambda(item i of xs, i, xs)
end repeat
return lst
end tell
end map
-- range :: Int -> Int -> [Int]
on range(m, n)
if n < m then
set d to -1
else
set d to 1
end if
set lst to {}
repeat with i from m to n by d
set end of lst to i
end repeat
return lst
end range
-- intercalate :: Text -> [Text] -> Text
on intercalate(strText, lstText)
set {dlm, my text item delimiters} to {my text item delimiters, strText}
set strJoined to lstText as text
set my text item delimiters to dlm
return strJoined
end intercalate
-- Lift 2nd class handler function into 1st class script wrapper
-- mReturn :: Handler -> Script
on mReturn(f)
if class of f is script then
f
else
script
property lambda : f
end script
end if
end mReturn

View file

@ -0,0 +1,14 @@
i = 99;
while (i > -1) {
print i , " bottles of beer on the wall\n";
print i , " bottles of beer\nTake one down, pass it around\n";
if (i == 2) {
break
}
print --i , " bottles of beer on the wall\n";
}
print --i , " bottle of beer on the wall\n";
print i , " bottle of beer on the wall\n";
print i , " bottle of beer\nTake it down, pass it around\nno more bottles of beer on the wall\n";
quit

View file

@ -0,0 +1,29 @@
[
dnrpr
dnlBP
lCP
1-dnrp
rd2r >L
]sL
[Take one down, pass it around
]sC
[ bottles of beer
]sB
[ bottles of beer on the wall]
99
lLx
dnrpsA
dnlBP
lCP
1-
dn[ bottle of beer on the wall]p
rdnrpsA
n[ bottle of beer
]P
[Take it down, pass it around
]P
[no more bottles of beer on the wall
]P

View file

@ -0,0 +1,32 @@
[
plAP
plBP
lCP
1-dplAP
d2r >L
]sL
[Take one down, pass it around
]sC
[bottles of beer
]sB
[bottles of beer on the wall
]sA
99
lLx
plAP
plBP
lCP
1-
p
[bottle of beer on the wall
]P
p
[bottle of beer
]P
[Take it down, pass it around
]P
[no more bottles of beer on the wall
]P

View file

@ -0,0 +1,33 @@
#import system.
#import system'dynamic.
#import system'routines.
#import extensions.
#import extensions'routines.
#import extensions'text.
#class(extension)bottleOp
{
#method bottleDescription
= self literal + (self != 1) iif:" bottles":" bottle".
#method bottleEnumerator = Variable new:self eval &with:target
[
Enumerator
{
next = target > 0.
get = StringWriter new
writeLine:(target bottleDescription):" of beer on the wall"
writeLine:(target bottleDescription):" of beer"
writeLine:"Take one down, pass it around"
writeLine:((target -= 1) bottleDescription):" of beer on the wall".
}
].
}
#symbol program =
[
#var bottles := 99.
bottles bottleEnumerator run &each:printingLn.
].

View file

@ -0,0 +1,9 @@
Pro bottles_noloop2
n_bottles=99
b1 = reverse(SINDGEN(n_bottles,START=1))
b2= reverse(SINDGEN(n_bottles))
wallT=replicate(' bottles of beer on the wall.', n_bottles)
wallT2=replicate(' bottles of beer.', n_bottles)
takeT=replicate('Take one down, pass it around,', n_bottles)
print, b1+wallT+string(10B)+b1+wallT2+string(10B)+takeT+string(10B)+b2+wallT+string(10B)
End

View file

@ -1,2 +1,11 @@
// Line breaks are in HTML
var beer; while ((beer = typeof beer === "undefined" ? 99 : beer) > 0) document.write( beer + " bottle" + (beer != 1 ? "s" : "") + " of beer on the wall<br>" + beer + " bottle" + (beer != 1 ? "s" : "") + " of beer<br>Take one down, pass it around<br>" + (--beer) + " bottle" + (beer != 1 ? "s" : "") + " of beer on the wall<br>" );
var bottles = 99;
var songTemplate = "{X} bottles of beer on the wall \n" +
"{X} bottles of beer \n"+
"Take one down, pass it around \n"+
"{X-1} bottles of beer on the wall \n";
function song(x, txt) {
return txt.replace(/\{X\}/gi, x).replace(/\{X-1\}/gi, x-1) + (x > 1 ? song(x-1, txt) : "");
}
console.log(song(bottles, songTemplate));

View file

@ -1,25 +1,2 @@
function Bottles(count) {
this.count = count || 99;
}
Bottles.prototype.take = function() {
var verse = [
this.count + " bottles of beer on the wall,",
this.count + " bottles of beer!",
"Take one down, pass it around",
(this.count - 1) + " bottles of beer on the wall!"
].join("\n");
console.log(verse);
this.count--;
};
Bottles.prototype.sing = function() {
while (this.count) {
this.take();
}
};
var bar = new Bottles(99);
bar.sing();
// Line breaks are in HTML
var beer; while ((beer = typeof beer === "undefined" ? 99 : beer) > 0) document.write( beer + " bottle" + (beer != 1 ? "s" : "") + " of beer on the wall<br>" + beer + " bottle" + (beer != 1 ? "s" : "") + " of beer<br>Take one down, pass it around<br>" + (--beer) + " bottle" + (beer != 1 ? "s" : "") + " of beer on the wall<br>" );

View file

@ -1,18 +1,25 @@
function bottleSong(n) {
if (!isFinite(Number(n)) || n == 0) n = 100;
var a = '%% bottles of beer',
b = ' on the wall',
c = 'Take one down, pass it around',
r = '<br>'
p = document.createElement('p'),
s = [],
re = /%%/g;
while(n) {
s.push((a+b+r+a+r+c+r).replace(re, n) + (a+b).replace(re, --n));
}
p.innerHTML = s.join(r+r);
document.body.appendChild(p);
function Bottles(count) {
this.count = count || 99;
}
window.onload = bottleSong;
Bottles.prototype.take = function() {
var verse = [
this.count + " bottles of beer on the wall,",
this.count + " bottles of beer!",
"Take one down, pass it around",
(this.count - 1) + " bottles of beer on the wall!"
].join("\n");
console.log(verse);
this.count--;
};
Bottles.prototype.sing = function() {
while (this.count) {
this.take();
}
};
var bar = new Bottles(99);
bar.sing();

View file

@ -0,0 +1,18 @@
function bottleSong(n) {
if (!isFinite(Number(n)) || n == 0) n = 100;
var a = '%% bottles of beer',
b = ' on the wall',
c = 'Take one down, pass it around',
r = '<br>'
p = document.createElement('p'),
s = [],
re = /%%/g;
while(n) {
s.push((a+b+r+a+r+c+r).replace(re, n) + (a+b).replace(re, --n));
}
p.innerHTML = s.join(r+r);
document.body.appendChild(p);
}
window.onload = bottleSong;

View file

@ -0,0 +1,77 @@
##################################
# 99 bottles of beer on the wall #
# MIPS Assembly targeting MARS #
# By Keith Stellyes #
# August 24, 2016 #
##################################
#It is simple, a loop that goes as follows:
#if accumulator is not 1:
#PRINT INTEGER: accumulator
#PRINT lyrica
#PRINT INTEGER: accumulator
#PRINT lyricb
#PRINT INTEGER: accumulator
#PRINT lyricc
#DECREMENT accumulator
#else:
#PRINT FINAL LYRICS
.data
lyrica: .asciiz " bottles of beer on the wall, "
lyricb: " bottles of beer.\nTake one down and pass it around, "
lyricc: " bottles of beer on the wall. \n\n"
#normally, I don't like going past 80 columns, but that was done here.
# there's an argument to be had for breaking this up. I chose not to
# for simpler instructions.
final_lyrics: "1 bottle of beer on the wall, 1 bottle of beer.\nTake one down and pass it around, no more bottles of beer on the wall.\n\nNo more bottles of beer on the wall, no more bottles of beer.\nGo to the store and buy some more, 99 bottles of beer on the wall."
.text
#lw $a0,accumulator #load address of accumulator into $a0 (or is it getting val?)
li $a1,99 #set the inital value of the counter to 99
loop:
###99
li $v0, 1 #specify print integer system service
move $a0,$a1
syscall #print that integer
### bottles of beer on the wall,
la $a0,lyrica
li $v0,4
syscall
###99
li $v0, 1 #specify print integer system service
move $a0,$a1
syscall #print that integer
### bottles of beer.\n Take one down and pass it around,
la $a0,lyricb
li $v0,4
syscall
###99
li $v0, 1 #specify print integer system service
move $a0,$a1
syscall #print that integer
### "bottles of beer on the wall. \n\n"
la $a0,lyricc
li $v0,4
syscall
#decrement counter, if at 1, print the final and exit.
subi $a1,$a1,1
bne $a1,1,loop
### PRINT FINAL LYRIC, THEN TERMINATE.
final: la $a0,final_lyrics
li $v0,4
syscall
li $v0,10
syscall

View file

@ -0,0 +1,12 @@
bottles
set template1="i_n_""of beer on the wall. ""_i_n_"" of beer. """
set template2="""Take""_n2_""down, pass it around. """
set template3="j_n3_""of beer on the wall."""
for i=99:-1:1 do write ! hang 1
. set:i>1 n=" bottles ",n2=" one " set:i=1 n=" bottle ",n2=" it "
. set n3=" bottle " set j=i-1 set:(j>1)!(j=0) n3=" bottles " set:j=0 j="No"
. write @template1,@template2,@template3
repeat
write "One more time!",! hang 5
goto bottles

View file

@ -0,0 +1,60 @@
% file: beer.m
% author:
% Fergus Henderson <fjh@cs.mu.oz.au> Thursday 9th November 1995
% Re-written with new syntax standard library calls:
% Paul Bone <paul@mercurylang.org> 2015-11-20
%
% This beer song is more idiomatic Mercury than the original, I feel bad
% saying that since Fergus is a founder of the language.
:- module beer.
:- interface.
:- import_module io.
:- pred main(io::di, io::uo) is det.
:- implementation.
:- import_module int.
:- import_module list.
:- import_module string.
main(!IO) :-
beer(99, !IO).
:- pred beer(int::in, io::di, io::uo) is det.
beer(N, !IO) :-
io.write_string(beer_stanza(N), !IO),
( N > 0 ->
io.nl(!IO),
beer(N - 1, !IO)
;
true
).
:- func beer_stanza(int) = string.
beer_stanza(N) = Stanza :-
( N = 0 ->
Stanza = "Go to the store and buy some more!\n"
;
NBottles = bottles_line(N),
N1Bottles = bottles_line(N - 1),
Stanza =
NBottles ++ " on the wall.\n" ++
NBottles ++ ".\n" ++
"Take one down, pass it around,\n" ++
N1Bottles ++ " on the wall.\n"
).
:- func bottles_line(int) = string.
bottles_line(N) =
( N = 0 ->
"No more bottles of beer"
; N = 1 ->
"1 bottle of beer"
;
string.format("%d bottles of beer", [i(N)])
).

View file

@ -0,0 +1,12 @@
class Bottles {
function : Main(args : String[]) ~ Nil {
bottles := 99;
do {
"{$bottles} bottles of beer on the wall"->PrintLine();
"{$bottles} bottles of beer"->PrintLine();
"Take one down, pass it around"->PrintLine();
bottles--;
"{$bottles} bottles of beer on the wall"->PrintLine();
} while(bottles > 0);
}
}

View file

@ -0,0 +1,16 @@
$Bottles {
dup cvs ` bottle' cat exch 1 ne {`s' cat} if
` of beer' cat
} def
$GetPronoun {
1 eq {`it'}{`one'} ifelse cat
} def
$WriteStanza {
dup dup Bottles ` on the wall. ' cat exch Bottles `.\n' cat cat
exch `Take ' 1 idup GetPronoun ` down. Pass it around.\n' cat
exch dec Bottles ` on the wall.\n\n' 3 {cat} repeat print flush
} def
99 -1 1 {WriteStanza} for

View file

@ -0,0 +1,3 @@
for (int i = 99; i > 0; i--) {
print(i + " bottles of beer on the wall\n" + i + " bottles of beer\nTake one down, pass it around\n" + (i - 1) + " bottles of beer on the wall\n\n");
}

View file

@ -1,20 +1,20 @@
/*REXX pgm displays lyrics to the song "99 Bottles of Beer on the Wall".*/
parse arg N .; if N=='' then N=99 /*let # bottles be specified*/
/*REXX program displays lyrics to the song "99 Bottles of Beer on the Wall". */
parse arg N .; if N=='' | N=="," then N=99 /*let number of bottles be given. */
do j=N by -1 to 1 /*start countdown & singdown*/
say j 'bottle's(j) "of beer on the wall," /*sing the #bottles of beer.*/
say j 'bottle's(j) "of beer." /* ··· and the refrain.*/
say 'Take one down, pass it around,' /*get a bottle and share it.*/
m=j-1 /*M: # bottles we have now.*/
if m==0 then m='no' /*use "no" instead of 0. */
say m 'bottle's(m) "of beer on the wall." /*sing beer bottle inventory*/
say /*blank line between verses.*/
end /*j*/
/*Not tanked? Then sing it.*/
say 'No more bottles of beer on the wall,' /*Finally! The last verse.*/
say 'no more bottles of beer.' /*this is so forlorn ··· */
say 'Go to the store and buy some more,' /*replenishment of the beer.*/
say N 'bottles of beer on the wall.' /*all is well in the tavern.*/
exit /*we're done & also sloshed.*/
/*───────────────────────────────────S subroutine───────────────────────*/
s: if arg(1)=1 then return ''; return 's' /*simple pluralizer function*/
do j=N by -1 to 1 /*start the countdown and singdown*/
say j 'bottle's(j) "of beer on the wall," /*sing the number bottles of beer.*/
say j 'bottle's(j) "of beer." /* ··· and the song's refrain.*/
say 'Take one down, pass it around,' /*take a beer bottle and share it.*/
m=j-1 /*M: number of bottles we have now*/
if m==0 then m='no' /*use "no" instead of numeric 0.*/
say m 'bottle's(m) "of beer on the wall." /*sing the beer bottle inventory. */
say /*a blank line between the verses.*/
end /*j*/
/*Not quite tanked? Then sing it.*/
say 'No more bottles of beer on the wall,' /*Finally! The last verse. */
say 'no more bottles of beer.' /*this is so forlorn ··· */
say 'Go to the store and buy some more,' /*obtain replenishment of the beer*/
say N 'bottles of beer on the wall.' /*all is well in the ole tavern. */
exit /*we're all done and also sloshed.*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
s: if arg(1)=1 then return ''; return 's' /*a simple pluralizer function. */

View file

@ -0,0 +1,16 @@
use std::borrow::Cow;
fn main() {
for i in (0..100).rev().map(|x| beer(x)) {
println!("{}", i)
}
}
fn beer(num: u32) -> Cow<'static, str> {
match num {
1=> "1 bottle of beer on the wall\n1 bottle of beer\nTake one down, pass it around".into(),
0 => "better go to the store and buy some more.".into(),
_ => (num.to_string() + " bottles of beer on the wall\n" +
&num.to_string() +" bottles of beer\nTake one down, pass it around\n" +
beer(num - 1).lines().nth(0).unwrap() + "\n").into(),
}
}

View file

@ -1,19 +1,20 @@
/*These statements work in PostgreSQL (tested in 9.3)*/
/*These statements work in PostgreSQL (tested in 9.4)*/
SELECT generate_series || ' bottles of beer on the wall' || chr(10) ||
generate_series || ' bottles of beer' || chr(10) ||
'Take one down, pass it around' || chr(10) ||
coalesce(lead(generate_series) OVER (ORDER BY generate_series DESC),0) || ' bottles of beer on the wall'
FROM generate_series(1,100)
coalesce(lead(generate_series) OVER (ORDER BY generate_series DESC),0) || ' bottles of beer on the wall' AS song
FROM generate_series(1,99)
ORDER BY generate_series DESC;
/*The next statement takes also into account the grammaticalt support for "1 bottle of beer".*/
/*The next statement takes also into account the grammatical support for "1 bottle of beer".*/
SELECT generate_series || ' bottle' || CASE WHEN generate_series>1 THEN 's' ELSE '' END || ' of beer on the wall' || chr(10) ||
generate_series || ' bottle' || CASE WHEN generate_series>1 THEN 's' ELSE '' END || ' of beer' || chr(10) ||
'Take one down, pass it around' || chr(10) ||
coalesce(lead(generate_series) OVER (ORDER BY generate_series DESC),0) || ' bottle' || CASE WHEN coalesce(lead(generate_series) OVER (ORDER BY generate_series DESC),0) <>1 THEN 's' ELSE '' END || ' of beer on the wall'
FROM generate_series(1,100)
coalesce(lead(generate_series) OVER (ORDER BY generate_series DESC),0) || ' bottle' || CASE WHEN coalesce(lead(generate_series) OVER (ORDER BY
generate_series DESC),0) <>1 THEN 's' ELSE '' END || ' of beer on the wall' AS song
FROM generate_series(1,99)
ORDER BY generate_series DESC;
/*The next statement uses recursive query.*/
@ -21,12 +22,12 @@ ORDER BY generate_series DESC;
WITH RECURSIVE t(n) AS (
VALUES (1)
UNION ALL
SELECT n+1 FROM t WHERE n < 100
SELECT n+1 FROM t WHERE n < 99
)
SELECT n || ' bottle' || CASE WHEN n>1 THEN 's' ELSE '' END || ' of beer on the wall' || chr(10) ||
n || ' bottle' || CASE WHEN n>1 THEN 's' ELSE '' END || ' of beer' || chr(10) ||
'Take one down, pass it around' || chr(10) ||
coalesce(lead(n) OVER (ORDER BY n DESC),0) || ' bottle' ||
CASE WHEN coalesce(lead(n) OVER (ORDER BY n DESC),0) <>1 THEN 's' ELSE '' END || ' of beer on the wall'
CASE WHEN coalesce(lead(n) OVER (ORDER BY n DESC),0) <>1 THEN 's' ELSE '' END || ' of beer on the wall' AS song
FROM t
ORDER BY n DESC;

View file

@ -0,0 +1,19 @@
// post to the REPL directly
(
(99..0).do { |n|
"% bottles of beer on the wall\n% bottles of beer\nTake one down, pass it around\n% bottles of beer on the wall\n".postf(n, n, n)
};
)
// post over time
(
fork {
100.reverseDo { |n|
n.post; " bottles of beer on the wall".postln; 0.5.wait;
n.post; " bottles of beer".postln; 0.5.wait;
"Take one down, pass it around".postln; 0.5.wait;
n.post; " bottles of beer on the wall".postln; 0.5.wait;
1.wait;
};
}
)

View file

@ -1,23 +1,30 @@
'''A+B''' - in programming contests, classic problem, which is given so contestants can gain familiarity with the online judging system being used.
<big>'''A+B'''</big> &nbsp; ─── a classic problem in programming contests, &nbsp; it's given so contestants can gain familiarity with the online judging system being used.
'''Problem statement'''<br>
Given 2 integer numbers, A and B. One needs to find their sum.
:'''Input data'''<br>
:Two integer numbers are written in the input stream, separated by space.
:<math>(-1000 \le A,B \le +1000)</math>
;Task:
Given two integer, &nbsp; '''A''' and '''B'''.
:'''Output data'''<br>
:The required output is one integer: the sum of A and B.
Their sum needs to be calculated.
:'''Example:'''<br>
;Input data:
Two integers are written in the input stream, separated by space(s):
: <big><math>(-1000 \le A,B \le +1000)</math></big>
;Output data:
The required output is one integer: &nbsp; the sum of '''A''' and '''B'''.
;Example:
::{|class="standard"
! Input
! Output
! input &nbsp;
! output &nbsp;
|-
|<tt>2 2</tt>
|<tt>4</tt>
|<tt> 2 2 </tt>
|<tt> 4 </tt>
|-
|<tt>3 2</tt>
|<tt>5</tt>
|<tt> 3 2 </tt>
|<tt> 5 </tt>
|}
<br><br>

View file

@ -1,7 +1,7 @@
on run argv
try
return ((first item of argv) as integer) + (second item of argv) as integer
on error
return "Usage with -1000 <= a,b <= 1000: " & tab & " A+B.scpt a b"
end try
try
return ((first item of argv) as integer) + (second item of argv) as integer
on error
return "Usage with -1000 <= a,b <= 1000: " & tab & " A+B.scpt a b"
end try
end run

View file

@ -0,0 +1,22 @@
ConsoleWrite("# A+B:" & @CRLF)
Func Sum($inp)
Local $num = StringSplit($inp, " "), $sum = 0
For $i = 1 To $num[0]
;~ ConsoleWrite("# num["&$i&"]:" & $num[$i] & @CRLF) ;;
$sum = $sum + $num[$i]
Next
Return $sum
EndFunc ;==>Sum
$inp = "17 4"
$res = Sum($inp)
ConsoleWrite($inp & " --> " & $res & @CRLF)
$inp = "999 42 -999"
ConsoleWrite($inp & " --> " & Sum($inp) & @CRLF)
; In calculations, text counts as 0,
; so the program works correctly even with this input:
Local $inp = "999x y 42 -999", $res = Sum($inp)
ConsoleWrite($inp & " --> " & $res & @CRLF)

View file

@ -1,4 +1,4 @@
$ read sys$command line
$ a = f$element( 0, " ", line )
$ b = f$element( 1, " ", line )
$ write sys$output a + b
$ write sys$output a, "+", b, "=", a + b

View file

@ -5,6 +5,7 @@ program SUM;
uses
SysUtils;
procedure
var
s1, s2:string;
begin

View file

@ -1,5 +1,5 @@
#define system.
#define extensions.
#import system.
#import extensions.
#symbol program =
[

5
Task/A+B/K/a+b.k Normal file
View file

@ -0,0 +1,5 @@
split:{(a@&~&/' y=/: a:(0,&x=y)_ x) _dv\: y}
ab:{+/0$split[0:`;" "]}
ab[]
2 3
5

25
Task/A+B/Onyx/a+b.onyx Normal file
View file

@ -0,0 +1,25 @@
$Prompt {
`\nEnter two numbers between -1000 and +1000,\nseparated by a space: ' print flush
} def
$GetNumbers {
mark stdin readline pop # Reads input as a string. Pop gets rid of false.
cvx eval # Convert string to integers.
} def
$CheckRange { # (n1 n2 -- bool)
dup -1000 ge exch 1000 le and
} def
$CheckInput {
counttomark 2 ne
{`You have to enter exactly two numbers.\n' print flush quit} if
2 ndup CheckRange exch CheckRange and not
{`The numbers have to be between -1000 and +1000.\n' print flush quit} if
} def
$Answer {
add cvs `The sum is ' exch cat `.\n' cat print flush
} def
Prompt GetNumbers CheckInput Answer

Some files were not shown because too many files have changed in this diff Show more