Add tasks for all the new languages

This commit is contained in:
Tina Müller 2016-12-05 23:44:36 +01:00
parent 9dc3c2bb62
commit bba7bfd280
13208 changed files with 134745 additions and 0 deletions

View file

@ -0,0 +1,110 @@
*-----------------------------------------------------------
* Title : 100Doors.X68
* Written by : G. A. Tippery
* Date : 2014-01-17
* Description: Solves "100 Doors" problem, see: http://rosettacode.org/wiki/100_doors
* Notes : Translated from C "Unoptimized" version, http://rosettacode.org/wiki/100_doors#unoptimized
* : No optimizations done relative to C version; "for("-equivalent loops could be optimized.
*-----------------------------------------------------------
*
* System-specific general console I/O macros (Sim68K, in this case)
*
PUTS MACRO
** Print a null-terminated string w/o CRLF **
** Usage: PUTS stringaddress
** Returns with D0, A1 modified
MOVEQ #14,D0 ; task number 14 (display null string)
LEA \1,A1 ; address of string
TRAP #15 ; display it
ENDM
*
PRINTN MACRO
** Print decimal integer from number in register
** Usage: PRINTN register
** Returns with D0,D1 modified
IFNC '\1','D1' ;if some register other than D1
MOVE.L \1,D1 ;put number to display in D1
ENDC
MOVE.B #3,D0
TRAP #15 ;display number in D1
*
* Generic constants
*
CR EQU 13 ;ASCII Carriage Return
LF EQU 10 ;ASCII Line Feed
*
* Definitions specific to this program
*
* Register usage:
* D3 == pass (index)
* D4 == door (index)
* A2 == Doors array pointer
*
SIZE EQU 100 ;Define a symbolic constant for # of doors
ORG $1000 ;Specify load address for program -- actual address system-specific
START: ; Execution starts here
LEA Doors,A2 ; make A2 point to Doors byte array
MOVEQ #0,D3
PassLoop:
CMP #SIZE,D3
BCC ExitPassLoop ; Branch on Carry Clear - being used as Branch on Higher or Equal
MOVE D3,D4
DoorLoop:
CMP #SIZE,D4
BCC ExitDoorLoop
NOT.B 0(A2,D4)
ADD D3,D4
ADDQ #1,D4
BRA DoorLoop
ExitDoorLoop:
ADDQ #1,D3
BRA PassLoop
ExitPassLoop:
* $28 = 40. bytes of code to this point. 32626 cycles so far.
* At this point, the result exists as the 100 bytes starting at address Doors.
* To get output, we must use methods specific to the particular hardware, OS, or
* emulator system that the code is running on. I use macros to "hide" some of the
* system-specific details; equivalent macros would be written for another system.
MOVEQ #0,D4
PrintLoop:
CMP #SIZE,D4
BCC ExitPrintLoop
PUTS DoorMsg1
MOVE D4,D1
ADDQ #1,D1 ; Convert index to 1-based instead of 0-based
PRINTN D1
PUTS DoorMsg2
TST.B 0(A2,D4) ; Is this door open (!= 0)?
BNE ItsOpen
PUTS DoorMsgC
BRA Next
ItsOpen:
PUTS DoorMsgO
Next:
ADDQ #1,D4
BRA PrintLoop
ExitPrintLoop:
* What to do at end of program is also system-specific
SIMHALT ;Halt simulator
*
* $78 = 120. bytes of code to this point, but this will depend on how the I/O macros are actually written.
* Cycle count is nearly meaningless, as the I/O hardware and routines will dominate the timing.
*
* Data memory usage
*
ORG $2000
Doors DCB.B SIZE,0 ;Reserve 100 bytes, prefilled with zeros
DoorMsg1 DC.B 'Door ',0
DoorMsg2 DC.B ' is ',0
DoorMsgC DC.B 'closed',CR,LF,0
DoorMsgO DC.B 'open',CR,LF,0
END START ;last line of source

View file

@ -0,0 +1,31 @@
\ Array of doors; init to empty; accessing a non-extant member will return
\ 'null', which is treated as 'false', so we don't need to initialize it:
[] var, doors
\ given a door number, get the value and toggle it:
: toggle-door \ n --
doors @ over a:@
not rot swap a:! drop ;
\ print which doors are open:
: .doors
(
doors @ over a:@ nip
if . space else drop then
) 1 100 loop ;
\ iterate over the doors, skipping 'n':
: main-pass \ n --
0
true
repeat
drop
dup toggle-door
over n:+
dup 101 <
while 2drop drop ;
\ calculate the first 100 doors:
' main-pass 1 100 loop
\ print the results:
.doors cr bye

View file

@ -0,0 +1,23 @@
shared void run() {
print("Open doors (naive): ``naive()``
Open doors (optimized): ``optimized()``");
}
shared {Integer*} naive(Integer count = 100) {
variable value doors = [ for (_ in 1..count) closed ];
for (step in 1..count) {
doors = [for (i->door in doors.indexed) let (index = i+1) if (step == 1 || step.divides(index)) then door.toggle() else door ];
}
return doors.indexesWhere((door) => door == opened).map(1.plusInteger);
}
shared {Integer*} optimized(Integer count = 100) =>
{ for (i in 1..count) i*i }.takeWhile(count.notSmallerThan);
shared abstract class Door(shared actual String string) of opened | closed {
shared formal Door toggle();
}
object opened extends Door("opened") { toggle() => closed; }
object closed extends Door("closed") { toggle() => opened; }

View file

@ -0,0 +1,37 @@
program
map
end
MAX_DOOR_NUMBER equate(100)
CRLF equate('<13,10>')
Doors byte,dim(MAX_DOOR_NUMBER)
Pass byte
DoorNumber byte
DisplayString cstring(2000)
ResultWindow window('Result'),at(,,133,291),center,double,auto
prompt('Door states:'),at(8,4),use(?PromptTitle)
text,at(8,16,116,266),use(DisplayString),boxed,vscroll,font('Courier New',,,,CHARSET:ANSI),readonly
end
code
Doors :=: false
loop Pass = 1 to MAX_DOOR_NUMBER
loop DoorNumber = Pass to MAX_DOOR_NUMBER by Pass
Doors[DoorNumber] = choose(Doors[DoorNumber], false, true)
end
end
clear(DisplayString)
loop DoorNumber = 1 to MAX_DOOR_NUMBER
DisplayString = DisplayString & format(DoorNumber, @n3) & ' is ' & choose(Doors[DoorNumber], 'opened', 'closed') & CRLF
end
open(ResultWindow)
accept
end
close(ResultWindow)
return

View file

@ -0,0 +1,8 @@
doors = [false] * 100
for pass til doors.length
for i from pass til doors.length by pass + 1
! = doors[i]
for i til doors.length
console.log 'Door %d is %s.', i + 1, if doors[i] then 'open' else 'closed'

View file

@ -0,0 +1,8 @@
10 D=100: DIMD(D): P=1
20 PRINT CHR$(147);"PASS: ";P
22 FOR I=P TO D STEP P: D(I)=NOTD(I): NEXT
30 IF P=100 THEN 40
32 P=P+1: GOTO20
40 PRINT: PRINT"THE FOLLOWING DOORS ARE OPEN: "
42 FOR I=1 TO D: IF D(I)=-1 THEN PRINTI;
44 NEXT

View file

@ -0,0 +1,11 @@
doors = Array.new(100, false)
1.upto(100) do |i|
i.step(by: i, limit: 100) do |j|
doors[j - 1] = !doors[j - 1]
end
end
doors.each_with_index do |open, i|
puts "Door #{i + 1} is #{open ? "open" : "closed"}"
end

View file

@ -0,0 +1,15 @@
Doors := RECORD
UNSIGNED1 DoorNumber;
STRING6 State;
END;
AllDoors := DATASET([{0,0}],Doors);
Doors OpenThem(AllDoors L,INTEGER Cnt) := TRANSFORM
SELF.DoorNumber := Cnt;
SELF.State := IF((CNT * 10) % (SQRT(CNT)*10)<>0,'Closed','Opened');
END;
OpenDoors := NORMALIZE(AllDoors,100,OpenThem(LEFT,COUNTER));
OpenDoors;

View file

@ -0,0 +1,30 @@
Doors := RECORD
UNSIGNED1 DoorNumber;
STRING6 State;
END;
AllDoors := DATASET([{0,'0'}],Doors);
//first build the 100 doors
Doors OpenThem(AllDoors L,INTEGER Cnt) := TRANSFORM
SELF.DoorNumber := Cnt;
SELF.State := 'Closed';
END;
ClosedDoors := NORMALIZE(AllDoors,100,OpenThem(LEFT,COUNTER));
//now iterate through them and use door logic
loopBody(DATASET(Doors) ds, UNSIGNED4 c) :=
PROJECT(ds, //ds=original input
TRANSFORM(Doors,
SELF.State := CASE((COUNTER % c) * 100,
0 => IF(LEFT.STATE = 'Opened','Closed','Opened')
,LEFT.STATE);
SELF.DoorNumber := COUNTER; //PROJECT COUNTER
));
g1 := LOOP(ClosedDoors,100,loopBody(ROWS(LEFT),COUNTER));
OUTPUT(g1);

View file

@ -0,0 +1,23 @@
DoorSet := DATASET(100,TRANSFORM({UNSIGNED1 DoorState},SELF.DoorState := 1));
SetDoors := SET(DoorSet,DoorState);
Doors := RECORD
UNSIGNED1 Pass;
SET OF UNSIGNED1 DoorSet;
END;
StartDoors := DATASET(100,TRANSFORM(Doors,SELF.Pass := COUNTER,SELF.DoorSet := SetDoors));
Doors XF(Doors L, Doors R) := TRANSFORM
ds := DATASET(L.DoorSet,{UNSIGNED1 DoorState});
NextDoorSet := PROJECT(ds,
TRANSFORM({UNSIGNED1 DoorState},
SELF.DoorState := CASE((COUNTER % R.Pass) * 100,
0 => IF(LEFT.DoorState = 1,0,1),
LEFT.DoorState)));
SELF.DoorSet := IF(L.Pass=0,R.DoorSet,SET(NextDoorSet,DoorState));
SELF.Pass := R.Pass
END;
Res := DATASET(ITERATE(StartDoors,XF(LEFT,RIGHT))[100].DoorSet,{UNSIGNED1 DoorState});
PROJECT(Res,TRANSFORM({STRING20 txt},SELF.Txt := 'Door ' + COUNTER + ' is ' + IF(LEFT.DoorState=1,'Open','Closed')));

View file

@ -0,0 +1,29 @@
! "100 Doors" program for ERRE LANGUAGE
! Author: Claudio Larini
! Date: 21-Nov-2014
!
! PC Unoptimized version translated from a QB version
PROGRAM 100DOORS
!$INTEGER
CONST N=100
DIM DOOR[N]
BEGIN
FOR STRIDE=1 TO N DO
FOR INDEX=STRIDE TO N STEP STRIDE DO
DOOR[INDEX]=NOT(DOOR[INDEX])
END FOR
END FOR
PRINT("Open doors:";)
FOR INDEX=1 TO N DO
IF DOOR[INDEX] THEN PRINT(INDEX;) END IF
END FOR
PRINT
END PROGRAM

View file

@ -0,0 +1,21 @@
; initial state = closed = #f
(define doors (make-vector 101 #f))
; run pass 100 to 1
(for*
((pass (in-range 100 0 -1))
(door (in-range 0 101 pass)))
(when (and
(vector-set! doors door (not (vector-ref doors door)))
(= pass 1))
(writeln door "is open")))
1 "is open"
4 "is open"
9 "is open"
16 "is open"
25 "is open"
36 "is open"
49 "is open"
64 "is open"
81 "is open"
100 "is open"

View file

@ -0,0 +1,16 @@
#import <Foundation/Foundation.h>
int main()
square := 1, increment = 3
for int door in 1 .. 100
printf("door #%d", door)
if door == square
puts(" is open.")
square += increment
increment += 2
else
puts(" is closed.")
return 0

View file

@ -0,0 +1,10 @@
READ x,y,z
PRINT "Open doors: ";x;" ";
CYCLE
z=x+y
PRINT z;" ";
x=z
y=y+2
REPEAT UNTIL z>=100
DATA 1,3,0
END

View file

@ -0,0 +1,32 @@
' version 27-10-2016
' compile with: fbc -s console
#Define max_doors 100
Dim As ULong c, n, n1, door(1 To max_doors)
' toggle, at start all doors are closed (0)
' 0 = door closed, 1 = door open
For n = 1 To max_doors
For n1 = n To max_doors Step n
door(n1) = 1 - door(n1)
Next
Next
' count the doors that are open (1)
Print "doors that are open nr: ";
For n = 1 To max_doors
If door(n) = 1 Then
Print n; " ";
c = c + 1
End If
Next
Print : Print
Print "There are " + Str(c) + " doors open"
' empty keyboard buffer
While InKey <> "" : Wend
Print : Print "hit any key to end program"
Sleep
End

View file

@ -0,0 +1,33 @@
' version 27-10-2016
' compile with: fbc -s console
#Define max_doors 100
Dim As ULong c, n, n1, door(1 To max_doors)
' at start all doors are closed
' simple add 1 each time we open or close a door
' doors with odd numbers are open
' doors with even numbers are closed
For n = 1 To max_doors
For n1 = n To max_doors Step n
door(n1) += 1
Next
Next
Print "doors that are open nr: ";
For n = 1 To max_doors
If door(n) And 1 Then
Print n; " ";
c = c + 1
End If
Next
Print : Print
Print "There are " + Str(c) + " doors open"
' empty keyboard buffer
While InKey <> "" : Wend
Print : Print "hit any key to end program"
Sleep
End

View file

@ -0,0 +1,21 @@
' version 27-10-2016
' compile with: fbc -s console
#Define max_doors 100
Dim As ULong c, n
Print "doors that are open nr: ";
For n = 1 To 10
Print n * n; " ";
c = c + 1
Next
Print : Print
Print "There are " + Str(c) + " doors open"
' empty keyboard buffer
While InKey <> "" : Wend
Print : Print "hit any key to end program"
Sleep
End

View file

@ -0,0 +1,3 @@
for i <- 1..100
r = foldl1( \a, b -> a xor b, [(a|i) | a <- 1..100] )
println( i + ' ' + (if r then 'open' else 'closed') )

View file

@ -0,0 +1,4 @@
import math.sqrt
for i <- 1..100
println( i + ' ' + (if sqrt(i) is Integer then 'open' else 'closed') )

View file

@ -0,0 +1,11 @@
fun main(n: int): [n]bool =
let is_open = replicate n False
loop (is_open) = for i < n do
let js = map (*i+1) (iota n)
let flips = map (fn j =>
if j < n
then unsafe !is_open[j]
else True -- Doesn't matter.
) js
in write js flips is_open
in is_open

View file

@ -0,0 +1,14 @@
include "ConsoleWindow"
dim as short door, square : square = 1
dim as short increment : increment = 3
for door = 1 to 100
if (door == square)
print "Door"; door; " is open."
square += increment
increment += 2
else
print "Door"; door; " is closed."
end if
next

View file

@ -0,0 +1,34 @@
'
' 100 doors problem
'
DIM doors!(101) ! use indices 1 to 100
@close_doors
@do_passes
@show_doors
'
PROCEDURE close_doors
ARRAYFILL doors!(),FALSE
RETURN
'
PROCEDURE do_passes
LOCAL i%,j%
FOR i%=1 TO 100
FOR j%=i% TO 100 STEP i%
doors!(j%)=NOT doors!(j%)
NEXT j%
NEXT i%
RETURN
'
PROCEDURE show_doors
LOCAL i%
OPENW 1
CLEARW 1
FOR i%=1 TO 100
IF doors!(i%)
PRINT "Door ";i%;" is open"
ENDIF
NEXT i%
PRINT "(press a key to end program)"
~INP(2)
CLOSEW 1
RETURN

View file

@ -0,0 +1,13 @@
#define ARRAY_ELEMENTS 100
PROCEDURE Main()
LOCAL aDoors := Array( ARRAY_ELEMENTS )
LOCAL i, j
AFill( aDoors, .F. )
FOR i := 1 TO ARRAY_ELEMENTS
FOR j := i TO ARRAY_ELEMENTS STEP i
aDoors[ j ] = ! aDoors[ j ]
NEXT
NEXT
AEval( aDoors, {|e, n| QQout( Padl(n,3) + " is " + Iif(aDoors[n], "*open*", "closed" ) + "|" ), Iif( n%5 == 0, Qout(), e:=NIL) } )
RETURN

View file

@ -0,0 +1,8 @@
#define ARRAY_ELEMENTS 100
PROCEDURE Main()
LOCAL aDoors := Array( ARRAY_ELEMENTS )
AFill( aDoors, .F. )
AEval( aDoors, {|e, n| aDoors[n] := e := Iif( Int(Sqrt(n))==Sqrt(n), .T., .F. ) } )
AEval( aDoors, {|e, n| QQout( Padl(n,3) + " is " + Iif(aDoors[n], "*open*", "closed" ) + "|" ), Iif( n%5 == 0, Qout(), e:=NIL )} )
RETURN

View file

@ -0,0 +1,10 @@
(def doors (* [False] 100))
(for [pass (range (len doors))]
(for [i (range pass (len doors) (inc pass))]
(assoc doors i (not (get doors i)))))
(for [i (range (len doors))]
(print (.format "Door {} is {}."
(inc i)
(if (get doors i) "open" "closed"))))

View file

@ -0,0 +1,18 @@
software {
var doors = len(100)
for pass over [1, 100]
var door = pass - 1
loop door < len(doors) {
doors[door] = doors[door]/0
door += pass
}
end
for door,isopen in doors
if isopen
print("Door ",door+1,": open")
end
end
print("All other doors are closed")
}

View file

@ -0,0 +1,35 @@
import Data.Vect
-- Creates list from 0 to n (not including n)
upTo : (m : Nat) -> Vect m (Fin m)
upTo Z = []
upTo (S n) = 0 :: (map FS (upTo n))
data DoorState = DoorOpen | DoorClosed
toggleDoor : DoorState -> DoorState
toggleDoor DoorOpen = DoorClosed
toggleDoor DoorClosed = DoorOpen
isOpen : DoorState -> Bool
isOpen DoorOpen = True
isOpen DoorClosed = False
initialDoors : Vect 100 DoorState
initialDoors = fromList $ map (\_ => DoorClosed) [1..100]
iterate : (n : Fin m) -> Vect m DoorState -> Vect m DoorState
iterate n doors {m} =
map (\(idx, doorState) =>
if ((S (finToNat idx)) `mod` (S (finToNat n))) == Z
then toggleDoor doorState
else doorState)
(zip (upTo m) doors)
-- Returns all doors left open at the end
solveDoors : List (Fin 100)
solveDoors =
findIndices isOpen $ foldl (\doors,val => iterate val doors) initialDoors (upTo 100)
main : IO ()
main = print $ map (\n => S (finToNat n)) solveDoors

View file

@ -0,0 +1,5 @@
loop(100) => {^
local(root = math_sqrt(loop_count))
local(state = (#root == math_ceil(#root) ? '<strong>open</strong>' | 'closed'))
#state != 'closed' ? 'Door ' + loop_count + ': ' + #state + '<br>'
^}

View file

@ -0,0 +1,15 @@
var doors = List.fill(100, false)
for i in 0...99:
for j in i...99 by i + 1:
doors[j] = !doors[j]
# The type must be specified since the list starts off empty.
var open_doors: List[Integer] = []
doors.each_index{|i|
if doors[i]:
open_doors.push(i + 1)
}
print($"Open doors: ^(open_doors)")

View file

@ -0,0 +1,9 @@
on mouseUp
repeat with tStep = 1 to 100
repeat with tDoor = tStep to 100 step tStep
put not tDoors[tDoor] into tDoors[tDoor]
end repeat
if tDoors[tStep] then put "Door " & tStep & " is open" & cr after tList
end repeat
set the text of field "Doors" to tList
end mouseUp

View file

@ -0,0 +1,8 @@
is_open = [false for door = 1,100]
for pass = 1,100
for door = pass,100,pass
is_open[door] = not is_open[door]
for i,v in ipairs is_open
print "Door #{i}: " .. if v then 'open' else 'closed'

View file

@ -0,0 +1,16 @@
from strutils import format
proc check_doors() =
const n = 100
var is_open : array[1..n, bool] # auto-initialized to false
# pass over the doors n times
for pass in 1..n:
var i = pass
while i <= n:
is_open[i] = not is_open[i]
i += pass
# print the result
for door in 1..n:
echo format("door $1 is $2.", door, (if is_open[door]: "open" else: "closed"))
check_doors()

View file

@ -0,0 +1,9 @@
var isOpen: array[1..100, bool]
for pass in countup(1, 100):
for door in countup(pass,100,pass):
isOpen[door] = not isOpen[door]
for i in countup(1, 100):
if isOpen[i]:
echo("Door ",i," is open.")

View file

@ -0,0 +1,7 @@
: doors
| i j l |
ListBuffer initValue(100, false) ->l
100 loop: i [
i 100 i step: j [ l put(j, l at(j) not) ]
]
l println ;

View file

@ -0,0 +1,22 @@
module doors;
extern printf;
@Integer main [
@Array<@Boolean> doors = new @Array<@Boolean>.init(100);
var i = 1;
while (i <= 100) {
var j = i-1;
while (j < 100) {
doors.set(j, doors.get(j)::not);
j = j + i;
}
i = i::inc;
}
i = 0;
while (i < 100) {
printf("%i %s\n", i+1, iif(doors.get(i), "open", "closed"));
i = i::inc;
}
return 0;
]

View file

@ -0,0 +1,26 @@
module var;
extern printf;
@Integer main [
var door = 1;
var incrementer = 0;
var current = 1;
while (current <= 100)
{
printf("Door %i ", current);
if (current == door)
{
printf("open\n");
incrementer = incrementer::inc;
door = door + 2 * incrementer + 1;
}
else
printf("closed\n");
current = current + 1;
}
return 0;
]

View file

@ -0,0 +1,79 @@
use perl5i::2;
package doors {
use perl5i::2;
use Const::Fast;
const my $OPEN => 1;
const my $CLOSED => 0;
# ----------------------------------------
# Constructor: door->new( @args );
# input: N - how many doors?
# returns: door object
#
method new($class: @args ) {
my $self = bless {}, $class;
$self->_init( @args );
return $self;
}
# ----------------------------------------
# class initializer.
# input: how many doors?
# sets N, creates N+1 doors ( door zero is not used ).
#
method _init( $N ) {
$self->{N} = $N;
$self->{doors} = [ ($CLOSED) x ($N+1) ];
}
# ----------------------------------------
# $self->toggle( $door_number );
# input: number of door to toggle.
# OPEN a CLOSED door; CLOSE an OPEN door.
#
method toggle( $which ) {
$self->{doors}[$which] = ( $self->{doors}[$which] == $OPEN
? $CLOSED
: $OPEN
);
}
# ----------------------------------------
# $self->toggle_n( $cycle );
# input: number.
# Toggle doors 0, $cycle, 2 * $cycle, 3 * $cycle, .. $self->{N}
#
method toggle_n( $n ) {
$self->toggle($_)
for map { $n * $_ }
( 1 .. int( $self->{N} / $n) );
}
# ----------------------------------------
# $self->toggle_all();
# Toggle every door, then every other door, every third door, ...
#
method toggle_all() {
$self->toggle_n( $_ ) for ( 1 .. $self->{N} );
}
# ----------------------------------------
# $self->print_open();
# Print list of which doors are open.
#
method print_open() {
say join ', ', grep { $self->{doors}[$_] == $OPEN } ( 1 ... $self->{N} );
}
}
# ----------------------------------------------------------------------
# Main Thread
#
my $doors = doors->new(100);
$doors->toggle_all();
$doors->print_open();

View file

@ -0,0 +1,13 @@
sequence doors = repeat(false,100)
for i=1 to 100 do
for j=i to 100 by i do
doors[j] = not doors[j]
end for
end for
for i=1 to 100 do
if doors[i] == true then
printf(1,"Door #%d is open.\n", i)
end if
end for

View file

@ -0,0 +1,13 @@
function doors(integer n)
-- returns the perfect squares<=n
integer door = 1, step = 1
sequence res = {}
while door<=n do
res &= door
step += 2
door += step
end while
return res
end function
?doors(100)

View file

@ -0,0 +1,7 @@
square=1, i=3
1 to 100(door):
if (door == square):
("door", door, "is open") say
square += i
i += 2.
.

View file

@ -0,0 +1,69 @@
data Door:
| open
| closed
end
fun flip-door(d :: Door) -> Door:
cases(Door) d:
| open => closed
| closed => open
end
end
fun flip-doors(doors :: List<Door>) -> List<Door>:
doc:```Given a list of door positions, repeatedly switch the positions of
every nth door for every nth pass, and return the final list of door
positions```
for fold(flipped-doors from doors, n from range(1, doors.length() + 1)):
for map_n(m from 1, d from flipped-doors):
if num-modulo(m, n) == 0:
flip-door(d)
else:
d
end
end
end
where:
flip-doors([list: closed, closed, closed]) is
[list: open, closed, closed]
flip-doors([list: closed, closed, closed, closed]) is
[list: open, closed, closed, open]
flip-doors([list: closed, closed, closed, closed, closed, closed]) is
[list: open, closed, closed, open, closed, closed]
closed-100 = for map(_ from range(1, 101)): closed end
answer-100 = for map(n from range(1, 101)):
if num-is-integer(num-sqrt(n)): open
else: closed
end
end
flip-doors(closed-100) is answer-100
end
fun find-indices<A>(pred :: (A -> Boolean), xs :: List<A>) -> List<Number>:
doc:```Given a list and a predicate function, produce a list of index
positions where there's a match on the predicate```
ps = map_n(lam(n,e): if pred(e): n else: -1 end end, 1, xs)
ps.filter(lam(x): x >= 0 end)
where:
find-indices((lam(i): i == true end), [list: true,false,true]) is [list:1,3]
end
fun run(n):
doc:```Given a list of doors that are closed, make repeated passes
over the list, switching the positions of every nth door for
each nth pass. Return a list of positions in the list where the
door is Open.```
doors = repeat(n, closed)
ys = flip-doors(doors)
find-indices((lam(y): y == open end), ys)
where:
run(4) is [list: 1,4]
end
run(100)

View file

@ -0,0 +1,20 @@
Red [
Purpose: "100 Doors Problem (Perfect Squares)"
Author: "Barry Arthur"
Date: "07-Oct-2016"
]
doors: make vector! [char! 8 100]
repeat i 100 [change at doors i #"."]
repeat i 100 [
j: i
while [j <= 100] [
door: at doors j
change door either #"O" = first door [#"."] [#"O"]
j: j + i
]
]
repeat i 10 [
print copy/part at doors (i - 1 * 10 + 1) 10
]

View file

@ -0,0 +1,17 @@
doors = list(100)
for i = 1 to 100
doors[i] = false
next
For pass = 1 To 100
For door = pass To 100
if doors[door] doors[door] = false else doors[door] = true ok
door += pass-1
Next
Next
For door = 1 To 100
see "Door (" + door + ") is "
If doors[door] see "Open" else see "Closed" ok
see nl
Next

View file

@ -0,0 +1,14 @@
doors = list(100)
for i = 1 to 100
doors[i] = false
next
For p = 1 To 10
doors[pow(p,2)] = True
Next
For door = 1 To 100
see "Door (" + door + ") is "
If doors[door] see "Open" else see "Closed" ok
see nl
Next

View file

@ -0,0 +1,14 @@
import <Utilities/Sequence.sl>;
main:=
let
doors := flipDoors(duplicate(false, 100), 1);
open[i] := i when doors[i];
in
open;
flipDoors(doors(1), count) :=
let
newDoors[i] := not doors[i] when i mod count = 0 else doors[i];
in
doors when count >= 100 else flipDoors(newDoors, count + 1);

View file

@ -0,0 +1,4 @@
main := flipDoors([1], 2);
flipDoors(openDoors(1), i) :=
openDoors when i * i >= 100 else flipDoors(openDoors ++ [i * i], i + 1);

View file

@ -0,0 +1,13 @@
var doors = []
100.times { |pass|
100.times { |i|
if (i % pass == 0) {
doors[i] := false -> not!
}
}
}
100.times { |i|
"Door %3d is %s\n".printf(i, doors[i] ? 'open' : 'closed')
}

View file

@ -0,0 +1,3 @@
{ |i|
"Door %3d is %s\n".printf(i, ["closed", "open"][i.is_sqr])
} * 100

View file

@ -0,0 +1,21 @@
/* declare the variables */
var isOpen = {};
var pass, door;
/* initialize the doors */
for door = 0; door < 100; door++ {
isOpen[door] = true;
}
/* do the 99 remaining passes */
for pass = 1; pass < 100; ++pass {
for door = pass; door < 100; door += pass+1 {
isOpen[door] = !isOpen[door];
}
}
/* print the results */
var states = { true: "open", false: "closed" };
for door = 0; door < 100; door++ {
printf("Door #%d is %s.\n", door+1, states[isOpen[door]]);
}

View file

@ -0,0 +1,13 @@
/* declare the variables */
var door_sqrt = 1;
var door;
/* print the perfect square doors as open */
for door = 0; door < 100; door++ {
if (door_sqrt*door_sqrt == door+1) {
printf("Door #%d is open.\n", door+1);
door_sqrt ++;
} else {
printf("Door #%d is closed.\n", door+1);
}
}

View file

@ -0,0 +1,21 @@
/* declare enum to identify the state of a door */
enum DoorState : String {
case Opened = "Opened"
case Closed = "Closed"
}
/* declare list of doors state and initialize them */
var doorsStateList = [DoorState](count: 100, repeatedValue: DoorState.Closed)
/* do the 100 passes */
for i in 1...100 {
/* map on a strideTo instance to only visit the needed doors on each iteration */
map(stride(from: i - 1, to: 100, by: i)) {
doorsStateList[$0] = doorsStateList[$0] == .Opened ? .Closed : .Opened
}
}
/* print the results */
for (index, item) in enumerate(doorsStateList) {
println("Door \(index+1) is \(item.rawValue)")
}

View file

@ -0,0 +1,20 @@
/* declare enum to identify the state of a door */
enum DoorState : String {
case Opened = "Opened"
case Closed = "Closed"
}
/* declare list of doors state and initialize them */
var doorsStateList = [DoorState](count: 100, repeatedValue: DoorState.Closed)
/* set i^2 doors to opened */
var i = 1
do {
doorsStateList[(i*i)-1] = DoorState.Opened
++i
} while (i*i) <= doorsStateList.count
/* print the results */
for (index, item) in enumerate(doorsStateList) {
println("Door \(index+1) is \(item.rawValue)")
}

View file

@ -0,0 +1,53 @@
entry LP_DO_IT
variables
string V_DOORS
boolean V_DOOR_STATE
string V_DOOR_STATE_S
numeric V_IDX
numeric V_TOTAL_DOORS
string V_DOOR_STATE_LIST
numeric V_LOOP_COUNT
endvariables
V_TOTAL_DOORS = 100
putitem V_DOORS, V_TOTAL_DOORS, 0
V_DOORS = $replace (V_DOORS, 1, "·;", "·;0", -1)
putitem/id V_DOOR_STATE_LIST, "1", "Open"
putitem/id V_DOOR_STATE_LIST, "0", "Close"
V_LOOP_COUNT = 1
while (V_LOOP_COUNT <= V_TOTAL_DOORS)
V_IDX = 0
V_IDX = V_IDX + V_LOOP_COUNT
getitem V_DOOR_STATE, V_DOORS, V_IDX
while (V_IDX <= V_TOTAL_DOORS)
V_DOOR_STATE = !V_DOOR_STATE
getitem/id V_DOOR_STATE_S, V_DOOR_STATE_LIST, $number(V_DOOR_STATE)
putitem V_DOORS, V_IDX, V_DOOR_STATE
V_IDX = V_IDX + V_LOOP_COUNT
getitem V_DOOR_STATE, V_DOORS, V_IDX
endwhile
V_LOOP_COUNT = V_LOOP_COUNT + 1
endwhile
V_IDX = 1
getitem V_DOOR_STATE, V_DOORS, V_IDX
while (V_IDX <= V_TOTAL_DOORS)
getitem/id V_DOOR_STATE_S, V_DOOR_STATE_LIST, $number(V_DOOR_STATE)
if (V_DOOR_STATE)
putmess "Door %%V_IDX%%% is finally %%V_DOOR_STATE_S%%%"
endif
V_IDX = V_IDX + 1
getitem V_DOOR_STATE, V_DOORS, V_IDX
endwhile
end ; LP_DO_IT

View file

@ -0,0 +1,30 @@
#
# 100 doors
#
decl int i j
decl boolean<> doors
# append 101 boolean values to doors stream
for (set i 0) (or (< i 100) (= i 100)) (inc i)
append false doors
end for
# loop through, opening and closing doors
for (set i 1) (or (< i 100) (= i 100)) (inc i)
for (set j i) (or (< j 100) (= j 100)) (inc j)
if (= (mod j i) 0)
set doors<j> (not doors<j>)
end if
end for
end for
# loop through and output which doors are open
for (set i 1) (or (< i 100) (= i 100)) (inc i)
out "Door " i ": " console
if doors<i>
out "open" endl console
else
out "closed" endl console
end if
end if

View file

@ -0,0 +1,10 @@
def (doors n)
let door (table)
for step 1 (step <= n) ++step
for j 0 (j < n) (j <- j+step)
zap! not door.j
for j 0 (j < n) ++j
when door.j
pr j
pr " "

View file

@ -0,0 +1,14 @@
; unoptimized
+^[
@var doors []
@for i rangei [1 100]
@for j rangei [i 100 i]
:!@not `j doors
@for i rangei [1 100]
@if `i doors
!console.log "door {i} is open"
]
; optimized, map square over 1 to 10
!*^@sq @to 10

View file

@ -0,0 +1,12 @@
var doors = [true] * 100
for (i in 1..100) {
var j = i
while(j < 100) {
doors[j] = !doors[j]
j = j + i + 1
}
}
for (i in 0...100) {
if (doors[i]) System.print(i + 1)
}

View file

@ -0,0 +1,7 @@
var door = 1
var increment = 3
while(door <= 100) {
System.print(door)
door = door + increment
increment = increment + 2
}

View file

@ -0,0 +1,13 @@
# Solution for n doors:
def doors(n):
def print:
. as $doors
| range(1; length+1)
| if $doors[.] then "Door \(.) is open" else empty end;
([][n+1] = null) as $doors
| reduce range(1; n+1) as $run
( $doors; reduce range($run; n+1; $run ) as $door
( .; .[$door] = (.[$door] | not) ) )
| print ;

View file

@ -0,0 +1,3 @@
# Solution for 100 doors:
def solution:
range(1;11) | "Door \(. * .) is open";

View file

@ -0,0 +1,311 @@
PROGRAM 24SOLVE
LABEL 98,99,2540,2550,2560
! possible brackets
CONST NBRACKETS=11,ST_CONST$="+-*/^("
DIM D[4],PERM[24,4]
DIM BRAKETS$[NBRACKETS]
DIM OP$[3]
DIM STACK$[50]
PROCEDURE COMPATTA_STACK
IF NS>1 THEN
R=1
WHILE R<NS DO
IF INSTR(ST_CONST$,STACK$[R])=0 AND INSTR(ST_CONST$,STACK$[R+1])=0 THEN
FOR R1=R TO NS-1 DO
STACK$[R1]=STACK$[R1+1]
END FOR
NS=NS-1
END IF
R=R+1
END WHILE
END IF
END PROCEDURE
PROCEDURE CALC_ARITM
L=NS1
WHILE L<=NS2 DO
IF STACK$[L]="^" THEN
IF L>=NS2 THEN GOTO 99 END IF
N1#=VAL(STACK$[L-1]) N2#=VAL(STACK$[L+1]) NOP=NOP-1
IF STACK$[L]="^" THEN
RI#=N1#^N2#
END IF
STACK$[L-1]=STR$(RI#)
N=L
WHILE N<=NS2-2 DO
STACK$[N]=STACK$[N+2]
N=N+1
END WHILE
NS2=NS2-2
L=NS1-1
END IF
L=L+1
END WHILE
L=NS1
WHILE L<=NS2 DO
IF STACK$[L]="*" OR STACK$[L]="/" THEN
IF L>=NS2 THEN GOTO 99 END IF
N1#=VAL(STACK$[L-1]) N2#=VAL(STACK$[L+1]) NOP=NOP-1
IF STACK$[L]="*" THEN
RI#=N1#*N2#
ELSE
IF N2#<>0 THEN RI#=N1#/N2# ELSE NERR=6 RI#=0 END IF
END IF
STACK$[L-1]=STR$(RI#)
N=L
WHILE N<=NS2-2 DO
STACK$[N]=STACK$[N+2]
N=N+1
END WHILE
NS2=NS2-2
L=NS1-1
END IF
L=L+1
END WHILE
L=NS1
WHILE L<=NS2 DO
IF STACK$[L]="+" OR STACK$[L]="-" THEN
EXIT IF L>=NS2
N1#=VAL(STACK$[L-1]) N2#=VAL(STACK$[L+1]) NOP=NOP-1
IF STACK$[L]="+" THEN RI#=N1#+N2# ELSE RI#=N1#-N2# END IF
STACK$[L-1]=STR$(RI#)
N=L
WHILE N<=NS2-2 DO
STACK$[N]=STACK$[N+2]
N=N+1
END WHILE
NS2=NS2-2
L=NS1-1
END IF
L=L+1
END WHILE
99:
IF NOP<2 THEN ! precedenza tra gli operatori
DB#=VAL(STACK$[NS1])
ELSE
IF NOP<3 THEN
DB#=VAL(STACK$[NS1+2])
ELSE
DB#=VAL(STACK$[NS1+4])
END IF
END IF
END PROCEDURE
PROCEDURE SVOLGI_PAR
NPA=NPA-1
FOR J=NS TO 1 STEP -1 DO
EXIT IF STACK$[J]="("
END FOR
IF J=0 THEN
NS1=1 NS2=NS CALC_ARITM NERR=7
ELSE
FOR R=J TO NS-1 DO
STACK$[R]=STACK$[R+1]
END FOR
NS1=J NS2=NS-1 CALC_ARITM
IF NS1=2 THEN
NS1=1 STACK$[1]=STACK$[2]
END IF
NS=NS1
COMPATTA_STACK
END IF
END PROCEDURE
PROCEDURE MYEVAL(EXPRESSION$,DB#,NERR->DB#,NERR)
NOP=0 NPA=0 NS=1 K$="" NERR=0
STACK$[1]="@" ! init stack
FOR W=1 TO LEN(EXPRESSION$) DO
LOOP
CODE=ASC(MID$(EXPRESSION$,W,1))
IF (CODE>=48 AND CODE<=57) OR CODE=46 THEN
K$=K$+CHR$(CODE)
W=W+1 IF W>LEN(EXPRESSION$) THEN GOTO 98 END IF
ELSE
EXIT IF K$=""
IF NS>1 OR (NS=1 AND STACK$[1]<>"@") THEN NS=NS+1 END IF
IF FLAG=0 THEN
STACK$[NS]=K$
ELSE
STACK$[NS]=STR$(VAL(K$)*FLAG)
END IF
K$="" FLAG=0
EXIT
END IF
END LOOP
IF CODE=43 THEN K$="+" END IF
IF CODE=45 THEN K$="-" END IF
IF CODE=42 THEN K$="*" END IF
IF CODE=47 THEN K$="/" END IF
IF CODE=94 THEN K$="^" END IF
CASE CODE OF
43,45,42,47,94-> ! +-*/^
IF MID$(EXPRESSION$,W+1,1)="-" THEN FLAG=-1 W=W+1 END IF
IF INSTR(ST_CONST$,STACK$[NS])<>0 THEN
NERR=5
ELSE
NS=NS+1 STACK$[NS]=K$ NOP=NOP+1
IF NOP>=2 THEN
FOR J=NS TO 1 STEP -1 DO
IF STACK$[J]<>"(" THEN GOTO 2540 END IF
IF J<NS-2 THEN GOTO 2550 ELSE GOTO 2560 END IF
2540: END FOR
2550: NS1=J+1 NS2=NS CALC_ARITM
NS=NS2 STACK$[NS]=K$
REGISTRO_X#=VAL(STACK$[NS-1])
END IF
END IF
2560: END ->
40-> ! (
IF NS>1 OR (NS=1 AND STACK$[1]<>"@") THEN NS=NS+1 END IF
STACK$[NS]="(" NPA=NPA+1
IF MID$(EXPRESSION$,W+1,1)="-" THEN FLAG=-1 W=W+1 END IF
END ->
41-> ! )
SVOLGI_PAR
IF NERR=7 THEN
NERR=0 NOP=0 NPA=0 NS=1
ELSE
IF NERR=0 OR NERR=1 THEN
DB#=VAL(STACK$[NS])
REGISTRO_X#=DB#
ELSE
NOP=0 NPA=0 NS=1
END IF
END IF
END ->
OTHERWISE
NERR=8
END CASE
K$=""
END FOR
98:
IF K$<>"" THEN
IF NS>1 OR (NS=1 AND STACK$[1]<>"@") THEN NS=NS+1 END IF
IF FLAG=0 THEN STACK$[NS]=K$ ELSE STACK$[NS]=STR$(VAL(K$)*FLAG) END IF
END IF
IF INSTR(ST_CONST$,STACK$[NS])<>0 THEN
NERR=6
ELSE
WHILE NPA<>0 DO
SVOLGI_PAR
END WHILE
IF NERR<>7 THEN NS1=1 NS2=NS CALCARITM END IF
END IF
NS=1 NOP=0 NPA=0
END PROCEDURE
BEGIN
PRINT(CHR$(12);) ! CLS
! possible brackets
DATA("4#4#4#4")
DATA("(4#4)#4#4")
DATA("4#(4#4)#4")
DATA("4#4#(4#4)")
DATA("(4#4)#(4#4)")
DATA("(4#4#4)#4")
DATA("4#(4#4#4)")
DATA("((4#4)#4)#4")
DATA("(4#(4#4))#4")
DATA("4#((4#4)#4)")
DATA("4#(4#(4#4))")
FOR I=1 TO NBRACKETS DO
READ(BRAKETS$[I])
END FOR
INPUT("ENTER 4 DIGITS: ",A$)
ND=0
FOR I=1 TO LEN(A$) DO
C$=MID$(A$,I,1)
IF INSTR("123456789",C$)>0 THEN
ND=ND+1
D[ND]=VAL(C$)
END IF
END FOR
! precompute permutations. dumb way.
NPERM=1*2*3*4
N=0
FOR I=1 TO 4 DO
FOR J=1 TO 4 DO
FOR K=1 TO 4 DO
FOR L=1 TO 4 DO
! valid permutation (no dupes)
IF I<>J AND I<>K AND I<>L AND J<>K AND J<>L AND K<>L THEN
N=N+1
! actually,we can as well permute given digits
PERM[N,1]=D[I]
PERM[N,2]=D[J]
PERM[N,3]=D[K]
PERM[N,4]=D[L]
END IF
END FOR
END FOR
END FOR
END FOR
! operations: full search
COUNT=0
OPS$="+-*/"
FOR OP1=1 TO 4 DO
OP$[1]=MID$(OPS$,OP1,1)
FOR OP2=1 TO 4 DO
OP$[2]=MID$(OPS$,OP2,1)
FOR OP3=1 TO 4 DO
OP$[3]=MID$(OPS$,OP3,1)
! substitute all brackets
FOR T=1 TO NBRACKETS DO
TMPL$=BRAKETS$[T]
! now,substitute all digits: permutations.
FOR P=1 TO NPERM DO
RES$=""
NOP=0
ND=0
FOR I=1 TO LEN(TMPL$) DO
C$=MID$(TMPL$,I,1)
CASE C$ OF
"#"-> ! operations
NOP=NOP+1
RES$=RES$+OP$[NOP]
END ->
"4"-> ! digits
ND=NOP+1
RES$=RES$+MID$(STR$(PERM[P,ND]),2)
END ->
OTHERWISE ! brackets goes here
RES$=RES$+C$
END CASE
END FOR
! eval here
MY_EVAL(RES$,DB#,NERR->DB#,NERR)
IF DB#=24 AND NERR=0 THEN
PRINT("24=";RES$)
COUNT=COUNT+1
END IF
END FOR
END FOR
END FOR
END FOR
END FOR
IF COUNT=0 THEN
PRINT("If you see this, probably task cannot be solved with these digits")
ELSE
PRINT("Total=";COUNT)
END IF
END PROGRAM

View file

@ -0,0 +1,111 @@
;; use task [[RPN_to_infix_conversion#EchoLisp]] to print results
(define (rpn->string rpn)
(if (vector? rpn)
(infix->string (rpn->infix rpn))
"😥 Not found"))
(string-delimiter "")
(define OPS #(* + - // )) ;; use float division
(define-syntax-rule (commutative? op) (or (= op *) (= op +)))
;; ---------------------------------
;; calc rpn -> num value or #f if bad rpn
;; rpn is a vector of ops or numbers
;; ----------------------------------
(define (calc rpn)
(define S (stack 'S))
(for ((token rpn))
(if (procedure? token)
(let [(op2 (pop S)) (op1 (pop S))]
(if (and op1 op2)
(push S (apply token (list op1 op2)))
(push S #f))) ;; not-well formed
(push S token ))
#:break (not (stack-top S)))
(if (= 1 (stack-length S)) (pop S) #f))
;; check for legal rpn -> #f if not legal
(define (rpn? rpn)
(define S (stack 'S))
(for ((token rpn))
(if (procedure? token)
(push S (and (pop S) (pop S)))
(push S token ))
#:break (not (stack-top S)))
(stack-top S))
;; --------------------------------------
;; build-rpn : push next rpn op or number
;; dleft is number of not used digits
;; ---------------------------------------
(define count 0)
(define (build-rpn into: rpn depth maxdepth digits ops dleft target &hit )
(define cmpop #f)
(cond
;; tooo long
[(> (++ count) 200_000) (set-box! &hit 'not-found)]
;; stop on first hit
[(unbox &hit) &hit]
;; partial rpn must be legal
[(not (rpn? rpn)) #f]
;; eval rpn if complete
[(> depth maxdepth)
(when (= target (calc rpn)) (set-box! &hit rpn))]
;; else, add a digit to rpn
[else
[when (< depth maxdepth) ;; digits anywhere except last
(for [(d digits) (i 10)]
#:continue (zero? d)
(vector-set! digits i 0) ;; mark used
(vector-set! rpn depth d)
(build-rpn rpn (1+ depth) maxdepth digits ops (1- dleft) target &hit)
(vector-set! digits i d)) ;; mark unused
] ;; add digit
;; or, add an op
;; ops anywhere except positions 0,1
[when (and (> depth 1) (<= (+ depth dleft) maxdepth));; cutter : must use all digits
(set! cmpop
(and (number? [rpn (1- depth)])
(number? [rpn (- depth 2)])
(> [rpn (1- depth)] [rpn (- depth 2)])))
(for [(op ops)]
#:continue (and cmpop (commutative? op)) ;; cutter : 3 4 + === 4 3 +
(vector-set! rpn depth op)
(build-rpn rpn (1+ depth) maxdepth digits ops dleft target &hit)
(vector-set! rpn depth 0))] ;; add op
] ; add something to rpn vector
)) ; build-rpn
;;------------------------
;;gen24 : num random numbers
;;------------------------
(define (gen24 num maxrange)
(->> (append (range 1 maxrange)(range 1 maxrange)) shuffle (take num)))
;;-------------------------------------------
;; try-rpn : sets starter values for build-rpn
;;-------------------------------------------
(define (try-rpn digits target)
(set! digits (list-sort > digits)) ;; seems to accelerate things
(define rpn (make-vector (1- (* 2 (length digits)))))
(define &hit (box #f))
(set! count 0)
(build-rpn rpn starter-depth: 0
max-depth: (1- (vector-length rpn))
(list->vector digits)
OPS
remaining-digits: (length digits)
target &hit )
(writeln target '= (rpn->string (unbox &hit)) 'tries= count))
;; -------------------------------
;; (task numdigits target maxrange)
;; --------------------------------
(define (task (numdigits 4) (target 24) (maxrange 10))
(define digits (gen24 numdigits maxrange))
(writeln digits '→ target)
(try-rpn digits target))

View file

@ -0,0 +1,121 @@
--
-- 24_game_solve.exw
-- =================
--
-- Write a function that given four digits subject to the rules of the 24 game, computes an expression to solve the game if possible.
-- Show examples of solutions generated by the function
--
-- The following 5 parse expressions are possible.
-- Obviously numbers 1234 represent 24 permutations from
-- {1,2,3,4} to {4,3,2,1} of indexes to the real numbers.
-- Likewise "+-*" is like "123" representing 64 combinations
-- from {1,1,1} to {4,4,4} of indexes to "+-*/".
-- Both will be replaced if/when the strings get printed.
--
constant OPS = "+-*/"
constant expressions = {"1+(2-(3*4))",
"1+((2-3)*4)",
"(1+2)-(3*4)",
"(1+(2-3))*4",
"((1+2)-3)*4"} -- (equivalent to "1+2-3*4")
--TODO: I'm sure there is a simple (recursive) way to programatically
-- generate the above (for n=2..9) but I'm not seeing it yet...
-- The above represented as three sequential operations (the result gets
-- left in <(map)1>, ie vars[perms[operations[i][3][1]]] aka vars[lhs]):
constant operations = {{{3,'*',4},{2,'-',3},{1,'+',2}}, --3*=4; 2-=3; 1+=2
{{2,'-',3},{2,'*',4},{1,'+',2}}, --2-=3; 2*=4; 1+=2
{{1,'+',2},{3,'*',4},{1,'-',3}}, --1+=2; 3*=4; 1-=3
{{2,'-',3},{1,'+',2},{1,'*',4}}, --2-=3; 1+=2; 1*=4
{{1,'+',2},{1,'-',3},{1,'*',4}}} --1+=2; 1-=3; 1*=4
--TODO: ... and likewise for parsing "expressions" to yield "operations".
function evalopset(sequence opset, sequence perms, sequence ops, sequence vars)
-- invoked 5*24*64 = 7680 times, to try all possible expressions/vars/operators
-- (btw, vars is copy-on-write, like all parameters not explicitly returned, so
-- we can safely re-use it without clobbering the callee version.)
integer lhs,op,rhs
atom inf
for i=1 to length(opset) do
{lhs,op,rhs} = opset[i]
lhs = perms[lhs]
op = ops[find(op,OPS)]
rhs = perms[rhs]
if op='+' then
vars[lhs] += vars[rhs]
elsif op='-' then
vars[lhs] -= vars[rhs]
elsif op='*' then
vars[lhs] *= vars[rhs]
elsif op='/' then
if vars[rhs]=0 then inf = 1e300*1e300 return inf end if
vars[lhs] /= vars[rhs]
end if
end for
return vars[lhs]
end function
integer nSolutions
sequence xSolutions
procedure success(string expr, sequence perms, sequence ops, sequence vars, atom r)
integer ch
for i=1 to length(expr) do
ch = expr[i]
if ch>='1' and ch<='9' then
expr[i] = vars[perms[ch-'0']]+'0'
else
ch = find(ch,OPS)
if ch then
expr[i] = ops[ch]
end if
end if
end for
if not find(expr,xSolutions) then
-- avoid duplicates for eg {1,1,2,7} because this has found
-- the "same" solution but with the 1st and 2nd 1s swapped,
-- and likewise whenever an operator is used more than once.
printf(1,"success: %s = %s\n",{expr,sprint(r)})
nSolutions += 1
xSolutions = append(xSolutions,expr)
end if
end procedure
procedure tryperms(sequence perms, sequence ops, sequence vars)
atom r
for i=1 to length(operations) do
-- 5 parse expressions
r = evalopset(operations[i], perms, ops, vars)
if r=24 then
success(expressions[i], perms, ops, vars, r)
end if
end for
end procedure
include builtins/factorial.e
include builtins/permute.e
procedure tryops(sequence ops, sequence vars)
for p=1 to factorial(4) do
-- 24 var permutations
tryperms(permute(p,{1,2,3,4}),ops, vars)
end for
end procedure
global procedure solve24(sequence vars)
nSolutions = 0
xSolutions = {}
for op1=1 to 4 do
for op2=1 to 4 do
for op3=1 to 4 do
-- 64 operator combinations
tryops({OPS[op1],OPS[op2],OPS[op3]},vars)
end for
end for
end for
printf(1,"\n%d solutions\n",{nSolutions})
end procedure
solve24({1,1,2,7})
if getc(0) then end if

View file

@ -0,0 +1,32 @@
var formats = [
'((%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))',
];
var op = %w( + - * / );
var operators = op.map { |a| op.map {|b| op.map {|c| "#{a} #{b} #{c}" } } }.flatten;
loop {
var input = Sys.scanln("Enter four integers or 'q' to exit: ");
input == 'q' && break;
input ~~ /^\h*[1-9]\h+[1-9]\h+[1-9]\h+[1-9]\h*$/ || (
say "Invalid input!"; next;
);
var n = input.split.map{.to_i};
var numbers = n.permute;
formats.each { |format|
numbers.each { |n|
operators.each { |operator|
var o = operator.split;
var str = (format % (n[0],o[0],n[1],o[1],n[2],o[2],n[3]));
eval(str) == 24 && say str;
}
}
}
}

View file

@ -0,0 +1,57 @@
var formats = [
{|a,b,c|
Hash.new(
func => {|d,e,f,g| ((d.$a(e)).$b(f)).$c(g) },
format => "((%d #{a} %d) #{b} %d) #{c} %d"
)
},
{|a,b,c|
Hash.new(
func => {|d,e,f,g| (d.$a((e.$b(f)))).$c(g) },
format => "(%d #{a} (%d #{b} %d)) #{c} %d",
)
},
{|a,b,c|
Hash.new(
func => {|d,e,f,g| (d.$a(e)).$b(f.$c(g)) },
format => "(%d #{a} %d) #{b} (%d #{c} %d)",
)
},
{|a,b,c|
Hash.new(
func => {|d,e,f,g| (d.$a(e)).$b(f.$c(g)) },
format => "(%d #{a} %d) #{b} (%d #{c} %d)",
)
},
{|a,b,c|
Hash.new(
func => {|d,e,f,g| d.$a(e.$b(f.$c(g))) },
format => "%d #{a} (%d #{b} (%d #{c} %d))",
)
},
];
var op = %w( + - * / );
var blocks = op.map { |a| op.map { |b| op.map { |c| formats.map { |format|
format(a,b,c)
}}}}.flatten;
loop {
var input = Sys.scanln("Enter four integers or 'q' to exit: ");
input == 'q' && break;
input ~~ /^\h*[1-9]\h+[1-9]\h+[1-9]\h+[1-9]\h*$/ || (
say "Invalid input!"; next;
);
var n = input.split.map{.to_num};
var numbers = n.permute;
blocks.each { |block|
numbers.each { |n|
if (block{:func}.call(n...) == 24) {
say (block{:format} % (n...));
}
}
}
}

View file

@ -0,0 +1,172 @@
import Darwin
import Foundation
var solution = ""
println("24 Game")
println("Generating 4 digits...")
func randomDigits() -> [Int] {
var result = [Int]()
for i in 0 ..< 4 {
result.append(Int(arc4random_uniform(9)+1))
}
return result
}
// Choose 4 digits
let digits = randomDigits()
print("Make 24 using these digits : ")
for digit in digits {
print("\(digit) ")
}
println()
// get input from operator
var input = NSString(data:NSFileHandle.fileHandleWithStandardInput().availableData, encoding:NSUTF8StringEncoding)!
var enteredDigits = [Double]()
var enteredOperations = [Character]()
let inputString = input as String
// store input in the appropriate table
for character in inputString {
switch character {
case "1", "2", "3", "4", "5", "6", "7", "8", "9":
let digit = String(character)
enteredDigits.append(Double(digit.toInt()!))
case "+", "-", "*", "/":
enteredOperations.append(character)
case "\n":
println()
default:
println("Invalid expression")
}
}
// check value of expression provided by the operator
var value = 0.0
if enteredDigits.count == 4 && enteredOperations.count == 3 {
value = enteredDigits[0]
for (i, operation) in enumerate(enteredOperations) {
switch operation {
case "+":
value = value + enteredDigits[i+1]
case "-":
value = value - enteredDigits[i+1]
case "*":
value = value * enteredDigits[i+1]
case "/":
value = value / enteredDigits[i+1]
default:
println("This message should never happen!")
}
}
}
func evaluate(dPerm: [Double], oPerm: [String]) -> Bool {
var value = 0.0
if dPerm.count == 4 && oPerm.count == 3 {
value = dPerm[0]
for (i, operation) in enumerate(oPerm) {
switch operation {
case "+":
value = value + dPerm[i+1]
case "-":
value = value - dPerm[i+1]
case "*":
value = value * dPerm[i+1]
case "/":
value = value / dPerm[i+1]
default:
println("This message should never happen!")
}
}
}
return (abs(24 - value) < 0.001)
}
func isSolvable(inout digits: [Double]) -> Bool {
var result = false
var dPerms = [[Double]]()
permute(&digits, &dPerms, 0)
let total = 4 * 4 * 4
var oPerms = [[String]]()
permuteOperators(&oPerms, 4, total)
for dig in dPerms {
for opr in oPerms {
var expression = ""
if evaluate(dig, opr) {
for digit in dig {
expression += "\(digit)"
}
for oper in opr {
expression += oper
}
solution = beautify(expression)
result = true
}
}
}
return result
}
func permute(inout lst: [Double], inout res: [[Double]], k: Int) -> Void {
for i in k ..< lst.count {
swap(&lst[i], &lst[k])
permute(&lst, &res, k + 1)
swap(&lst[k], &lst[i])
}
if k == lst.count {
res.append(lst)
}
}
// n=4, total=64, npow=16
func permuteOperators(inout res: [[String]], n: Int, total: Int) -> Void {
let posOperations = ["+", "-", "*", "/"]
let npow = n * n
for i in 0 ..< total {
res.append([posOperations[(i / npow)], posOperations[((i % npow) / n)], posOperations[(i % n)]])
}
}
func beautify(infix: String) -> String {
let newString = infix as NSString
var solution = ""
solution += newString.substringWithRange(NSMakeRange(0, 1))
solution += newString.substringWithRange(NSMakeRange(12, 1))
solution += newString.substringWithRange(NSMakeRange(3, 1))
solution += newString.substringWithRange(NSMakeRange(13, 1))
solution += newString.substringWithRange(NSMakeRange(6, 1))
solution += newString.substringWithRange(NSMakeRange(14, 1))
solution += newString.substringWithRange(NSMakeRange(9, 1))
return solution
}
if value != 24 {
println("The value of the provided expression is \(value) instead of 24!")
if isSolvable(&enteredDigits) {
println("A possible solution could have been " + solution)
} else {
println("Anyway, there was no known solution to this one.")
}
} else {
println("Congratulations, you found a solution!")
}

View file

@ -0,0 +1,40 @@
# Generate a stream of the permutations of the input array.
def permutations:
if length == 0 then []
else
. as $in | range(0;length) | . as $i
| ($in|del(.[$i])|permutations)
| [$in[$i]] + .
end ;
# Generate a stream of arrays of length n,
# with members drawn from the input array.
def take(n):
length as $l |
if n == 1 then range(0;$l) as $i | [ .[$i] ]
else take(n-1) + take(1)
end;
# Emit an array with elements that alternate between those in the input array and those in short,
# starting with the former, and using nothing if "short" is too too short.
def intersperse(short):
. as $in
| reduce range(0;length) as $i
([]; . + [ $in[$i], (short[$i] // empty) ]);
# Emit a stream of all the nested triplet groupings of the input array elements,
# e.g. [1,2,3,4,5] =>
# [1,2,[3,4,5]]
# [[1,2,3],4,5]
#
def triples:
. as $in
| if length == 3 then .
elif length == 1 then $in[0]
elif length < 3 then empty
else
(range(0; (length-1) / 2) * 2 + 1) as $i
| ($in[0:$i] | triples) as $head
| ($in[$i+1:] | triples) as $tail
| [$head, $in[$i], $tail]
end;

View file

@ -0,0 +1,23 @@
# Evaluate the input, which must be a number or a triple: [x, op, y]
def eval:
if type == "array" then
.[1] as $op
| if .[0] == null or .[2] == null then null
else
(.[0] | eval) as $left | (.[2] | eval) as $right
| if $left == null or $right == null then null
elif $op == "+" then $left + $right
elif $op == "-" then $left - $right
elif $op == "*" then $left * $right
elif $op == "/" then
if $right == 0 then null
else $left / $right
end
else "invalid arithmetic operator: \($op)" | error
end
end
else .
end;
def pp:
"\(.)" | explode | map([.] | implode | if . == "," then " " elif . == "\"" then "" else . end) | join("");

View file

@ -0,0 +1,21 @@
def OPERATORS: ["+", "-", "*", "/"];
# Input: an array of 4 digits
# o: an array of 3 operators
# Output: a stream
def EXPRESSIONS(o):
intersperse( o ) | triples;
def solve(objective):
length as $length
| [ (OPERATORS | take($length-1)) as $poperators
| permutations | EXPRESSIONS($poperators)
| select( eval == objective)
] as $answers
| if $answers|length > 3 then "That was too easy. I found \($answers|length) answers, e.g. \($answers[0] | pp)"
elif $answers|length > 1 then $answers[] | pp
else "You lose! There are no solutions."
end
;
solve(24), "Please try again."

View file

@ -0,0 +1,16 @@
$ jq -r -f Solve.jq
[1,2,3,4]
That was too easy. I found 242 answers, e.g. [4 * [1 + [2 + 3]]]
Please try again.
[1,2,3,40,1]
That was too easy. I found 636 answers, e.g. [[[1 / 2] * 40] + [3 + 1]]
Please try again.
[3,8,9]
That was too easy. I found 8 answers, e.g. [[8 / 3] * 9]
Please try again.
[4,5,6]
You lose! There are no solutions.
Please try again.
[1,2,3,4,5,6]
That was too easy. I found 197926 answers, e.g. [[2 * [1 + 4]] + [3 + [5 + 6]]]
Please try again.

View file

@ -0,0 +1,109 @@
\ Generate four random digits and display to the user
\ then get an expression from the user using +, -, / and * and the digits
\ the result must equal 24
\ http://8th-dev.com/24game.html
\ Only the words in namespace 'game' are available to the player:
ns: game
: + n:+ ;
: - n:- ;
: * n:* ;
: / n:/ ;
ns: G
var random-digits
var user-input
: one-digit \ a -- a
rand n:abs 9 n:mod n:1+ a:push ;
: gen-digits \ - a
[] clone nip \ the clone nip is not needed in versions past 1.0.2...
' one-digit 4 times
' n:cmp a:sort
random-digits ! ;
: prompt-user
cr "The digits are: " . random-digits @ . cr ;
: goodbye
cr "Thanks for playing!\n" . cr 0 die ;
: get-input
70 null con:accept dup user-input !
null? if drop goodbye then ;
: compare-digits
true swap
(
\ inputed-array index
dup >r
a:@
random-digits @ r> a:@ nip
n:= not if
break
swap drop false swap
then
) 0 3 loop drop ;
/^\D*(\d)\D+(\d)\D+(\d)\D+(\d)\D*$/ var, digits-regex
: all-digits?
user-input @ digits-regex @ r:match
null? if drop false else
5 = not if
false
else
\ convert the captured digits in the regex into a sorted array:
digits-regex @
( r:@ >n swap ) 1 4 loop drop
4 a:close ' n:cmp a:sort
compare-digits
then
then ;
: does-eval?
0 user-input @ eval 24 n:=
dup not if
cr "Sorry, that expression is wrong" . cr
then ;
: check-input
reset
all-digits? if
does-eval? if
cr "Excellent! Your expression: \"" .
user-input @ .
"\" worked!" . cr
then
else
cr "You did not use the digits properly, try again." . cr
then ;
: intro quote |
Welcome to the '24 game'!
You will be shown four digits each time. Using only the + - * and / operators
and all the digits (and only the digits), produce the number '24'
Enter your result in 8th syntax, e.g.: 4 4 + 2 1 + *
To quit the game, just hit enter by itself. Enjoy!
| . ;
: start
\ don't allow anything but the desired words
ns:game only
intro
repeat
gen-digits
prompt-user
get-input
check-input
again ;
start

View file

@ -0,0 +1,221 @@
import ceylon.random {
DefaultRandom
}
class Rational(shared Integer numerator, shared Integer denominator = 1) satisfies Numeric<Rational> {
assert(denominator != 0);
Integer gcd(Integer a, Integer b) => if(b == 0) then a else gcd(b, a % b);
shared Rational inverted => Rational(denominator, numerator);
shared Rational simplified =>
let(largestFactor = gcd(numerator, denominator))
Rational(numerator / largestFactor, denominator / largestFactor);
divided(Rational other) => (this * other.inverted).simplified;
negated => Rational(-numerator, denominator).simplified;
plus(Rational other) =>
let(top = numerator * other.denominator + other.numerator * denominator,
bottom = denominator * other.denominator)
Rational(top, bottom).simplified;
times(Rational other) =>
Rational(numerator * other.numerator, denominator * other.denominator).simplified;
shared Integer integer => numerator / denominator;
shared Float float => numerator.float / denominator.float;
string => denominator == 1 then numerator.string else "``numerator``/``denominator``";
}
interface Expression {
shared formal Rational evaluate();
}
class NumberExpression(Rational number) satisfies Expression {
evaluate() => number;
string => number.string;
}
class OperatorExpression(Expression left, Character operator, Expression right) satisfies Expression {
shared actual Rational evaluate() {
switch(operator)
case('*') {
return left.evaluate() * right.evaluate();
}
case('/') {
return left.evaluate() / right.evaluate();
}
case('-') {
return left.evaluate() - right.evaluate();
}
case('+') {
return left.evaluate() + right.evaluate();
}
else {
throw Exception("unknown operator ``operator``");
}
}
string => "(``left.string`` ``operator.string`` ``right.string``)";
}
"A simplified top down operator precedence parser. There aren't any right
binding operators so we don't have to worry about that."
class PrattParser(String input) {
value tokens = input.replace(" ", "");
variable value index = -1;
shared Expression expression(Integer precedence = 0) {
value token = advance();
variable value left = parseUnary(token);
while(precedence < getPrecedence(peek())) {
value nextToken = advance();
left = parseBinary(left, nextToken);
}
return left;
}
Integer getPrecedence(Character op) =>
switch(op)
case('*' | '/') 2
case('+' | '-') 1
else 0;
Character advance(Character? expected = null) {
index++;
value token = tokens[index] else ' ';
if(exists expected, token != expected) {
throw Exception("unknown character ``token``");
}
return token;
}
Character peek() => tokens[index + 1] else ' ';
Expression parseBinary(Expression left, Character operator) =>
let(right = expression(getPrecedence(operator)))
OperatorExpression(left, operator, right);
Expression parseUnary(Character token) {
if(token.digit) {
assert(exists int = parseInteger(token.string));
return NumberExpression(Rational(int));
} else if(token == '(') {
value exp = expression();
advance(')');
return exp;
} else {
throw Exception("unknown character ``token``");
}
}
}
"Run the module `twentyfourgame`."
shared void run() {
value random = DefaultRandom();
function random4Numbers() =>
random.elements(1..9).take(4).sequence();
function isValidGuess(String input, {Integer*} allowedNumbers) {
value allowedOperators = set {*"()+-/*"};
value extractedNumbers = input
.split((Character ch) => ch in allowedOperators || ch.whitespace)
.map((String element) => parseInteger(element))
.coalesced;
if(extractedNumbers.any((Integer element) => element > 9)) {
print("number too big!");
return false;
}
if(extractedNumbers.any((Integer element) => element < 1)) {
print("number too small!");
return false;
}
if(extractedNumbers.sort(byIncreasing(Integer.magnitude)) != allowedNumbers.sort(byIncreasing(Integer.magnitude))) {
print("use all the numbers, please!");
return false;
}
if(!input.every((Character element) => element in allowedOperators || element.digit || element.whitespace)) {
print("only digits and mathematical operators, please");
return false;
}
variable value lefts = 0;
for(c in input) {
if(c == '(') {
lefts++;
} else if(c == ')') {
lefts--;
if(lefts < 0) {
break;
}
}
}
if(lefts != 0) {
print("unbalanced brackets!");
return false;
}
return true;
}
function evaluate(String input) =>
let(parser = PrattParser(input),
exp = parser.expression())
exp.evaluate();
print("Welcome to The 24 Game.
Create a mathematical equation with four random
numbers that evaluates to 24.
You must use all the numbers once and only once,
but in any order.
Also, only + - / * and parentheses are allowed.
For example: (1 + 2 + 3) * 4
Also: enter n for new numbers and q to quit.
-----------------------------------------------");
while(true) {
value chosenNumbers = random4Numbers();
void pleaseTryAgain() => print("Sorry, please try again. (Your numbers are ``chosenNumbers``)");
print("Your numbers are ``chosenNumbers``. Please turn them into 24.");
while(true) {
value line = process.readLine()?.trimmed;
if(exists line) {
if(line.uppercased == "Q") {
print("bye!");
return;
}
if(line.uppercased == "N") {
break;
}
if(isValidGuess(line, chosenNumbers)) {
try {
value result = evaluate(line);
print("= ``result``");
if(result.integer == 24) {
print("You did it!");
break;
} else {
pleaseTryAgain();
}
} catch(Exception e) {
print(e.message);
pleaseTryAgain();
}
} else {
pleaseTryAgain();
}
}
}
}
}

View file

@ -0,0 +1,31 @@
(string-delimiter "")
;; check that nums are in expr, and only once
(define (is-valid? expr sorted: nums)
(when (equal? 'q expr) (error "24-game" "Thx for playing"))
(unless (and
(list? expr)
(equal? nums (list-sort < (filter number? (flatten expr)))))
(writeln "🎃 Please use" nums)
#f))
;; 4 random digits
(define (gen24)
(->> (append (range 1 10)(range 1 10)) shuffle (take 4) (list-sort < )))
(define (is-24? num)
(unless (= 24 num)
(writeln "😧 Sorry - Result = " num)
#f))
(define (check-24 expr)
(if (and
(is-valid? expr nums)
(is-24? (js-eval (string expr)))) ;; use js evaluator
"🍀 🌸 Congrats - (play24) for another one."
(input-expr check-24 (string nums))))
(define nums null)
(define (play24)
(set! nums (gen24))
(writeln "24-game - Can you combine" nums "to get 24 ❓ (q to exit)")
(input-expr check-24 (string-append (string nums) " -> 24 ❓")))

View file

@ -0,0 +1,70 @@
[
if(sys_listunboundmethods !>> 'randoms') => {
define randoms()::array => {
local(out = array)
loop(4) => { #out->insert(math_random(9,1)) }
return #out
}
}
if(sys_listunboundmethods !>> 'checkvalid') => {
define checkvalid(str::string, nums::array)::boolean => {
local(chk = array('*','/','+','-','(',')',' '), chknums = array, lastintpos = -1, poscounter = 0)
loop(9) => { #chk->insert(loop_count) }
with s in #str->values do => {
#poscounter++
#chk !>> #s && #chk !>> integer(#s) ? return false
integer(#s) > 0 && #lastintpos + 1 >= #poscounter ? return false
integer(#s) > 0 ? #chknums->insert(integer(#s))
integer(#s) > 0 ? #lastintpos = #poscounter
}
#chknums->size != 4 ? return false
#nums->sort
#chknums->sort
loop(4) => { #nums->get(loop_count) != #chknums(loop_count) ? return false }
return true
}
}
if(sys_listunboundmethods !>> 'executeexpr') => {
define executeexpr(expr::string)::integer => {
local(keep = string)
with i in #expr->values do => {
if(array('*','/','+','-','(',')') >> #i) => {
#keep->append(#i)
else
integer(#i) > 0 ? #keep->append(decimal(#i))
}
}
return integer(sourcefile('['+#keep+']','24game',true,true)->invoke)
}
}
local(numbers = array, exprsafe = true, exprcorrect = false, exprresult = 0)
if(web_request->param('nums')->asString->size) => {
with n in web_request->param('nums')->asString->split(',') do => { #numbers->insert(integer(#n->trim&)) }
}
#numbers->size != 4 ? #numbers = randoms()
if(web_request->param('nums')->asString->size) => {
#exprsafe = checkvalid(web_request->param('expr')->asString,#numbers)
if(#exprsafe) => {
#exprresult = executeexpr(web_request->param('expr')->asString)
#exprresult == 24 ? #exprcorrect = true
}
}
]<h1>24 Game</h1>
<p><b>Rules:</b><br>
Enter an expression that evaluates to 24</p>
<ul>
<li>Only multiplication, division, addition, and subtraction operators/functions are allowed.</li>
<li>Brackets are allowed.</li>
<li>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).</li>
<li>The order of the digits when given does not have to be preserved.</li>
</ul>
<h2>Numbers</h2>
<p>[#numbers->join(', ')] (<a href="?">Reload</a>)</p>
[!#exprsafe ? '<p>Please provide a valid expression</p>']
<form><input type="hidden" value="[#numbers->join(',')]" name="nums"><input type="text" name="expr" value="[web_request->param('expr')->asString]"><input type="submit" name="submit" value="submit"></form>
[if(#exprsafe)]
<p>Result: <b>[#exprresult]</b> [#exprcorrect ? 'is CORRECT!' | 'is incorrect']</p>
[/if]

View file

@ -0,0 +1,5 @@
on mouseUp
put empty into fld "EvalField"
put empty into fld "AnswerField"
put random(9) & comma & random(9) & comma & random(9) & comma & random(9) into fld "YourNumbersField"
end mouseUp

View file

@ -0,0 +1,30 @@
on keyDown k
local ops, nums, allowedKeys, numsCopy, expr
put "+,-,/,*,(,)" into ops
put the text of fld "YourNumbersField" into nums
put the text of fld "EvalField" into expr
if matchText(expr & k,"\d\d") then
answer "You can't enter 2 digits together"
exit keyDown
end if
repeat with n = 1 to the number of chars of expr
if offset(char n of expr, nums) > 0 then
delete char offset(char n of expr, nums) of nums
end if
end repeat
put ops & comma & nums into allowedKeys
if k is among the items of allowedKeys then
put k after expr
delete char offset(k, nums) of nums
replace comma with empty in nums
try
put the value of merge("[[expr]]") into fld "AnswerField"
if the value of fld "AnswerField" is 24 and nums is empty then
answer "You win!"
end if
end try
pass keyDown
else
exit keyDown
end if
end keyDown

View file

@ -0,0 +1,40 @@
import math, strutils, algorithm, sequtils
randomize()
template newSeqWith(len: int, init: expr): expr =
var result {.gensym.} = newSeq[type(init)](len)
for i in 0 .. <len:
result[i] = init
result
var
problem = newSeqWith(4, random(1..9))
stack = newSeq[float]()
digits = newSeq[int]()
echo "Make 24 with the digits: ", problem
template op(c): stmt =
let a = stack.pop
stack.add c(stack.pop, a)
for c in stdin.readLine:
case c
of '1'..'9':
digits.add c.ord - '0'.ord
stack.add float(c.ord - '0'.ord)
of '+': op `+`
of '*': op `*`
of '-': op `-`
of '/': op `/`
of Whitespace: discard
else: raise ValueError.newException "Wrong char: " & c
sort digits, cmp[int]
sort problem, cmp[int]
if digits.deduplicate != problem.deduplicate:
raise ValueError.newException "Not using the given digits."
if stack.len != 1:
raise ValueError.newException "Wrong expression."
echo "Result: ", stack[0]
echo if abs(stack[0] - 24) < 0.001: "Good job!" else: "Try again."

View file

@ -0,0 +1,19 @@
: 24game
| l expr w n i |
ListBuffer init(4, #[ 9 rand ]) ->l
System.Out "Digits : " << l << " --> RPN Expression for 24 : " << drop
System.Console askln ->expr
expr words forEach: w [
w "+" == ifTrue: [ + continue ]
w "-" == ifTrue: [ - continue ]
w "*" == ifTrue: [ * continue ]
w "/" == ifTrue: [ asFloat / continue ]
w asInteger dup ->n ifNull: [ System.Out "Word " << w << " not allowed " << cr break ]
l indexOf(n) dup ->i ifNull: [ System.Out "Integer " << n << " is wrong " << cr break ]
n l put(i, null)
]
l conform(#isNull) ifFalse: [ "Sorry, all numbers must be used..." println return ]
24 == ifTrue: [ "You won !" ] else: [ "You loose..." ] println ;

View file

@ -0,0 +1,177 @@
-- Note this uses simple/strict left association, so for example:
-- 1+2*1*8 is ((1+2)*1)*8 not 1+((2*1)*8) [or 1+(2*(1*8))], and
-- 7-(2*2)*8 is (7-(2*2))*8 not 7-((2*2)*8)
-- Does not allow unary minus on the first digit.
-- Uses solve24() from the next task, when it can.
-- (you may want to comment out the last 2 lines/uncomment the if 0, in that file)
--
--include 24_game_solve.exw
--with trace
forward function eval(string equation, sequence unused, integer idx=1)
-- (the above definition is entirely optional, but good coding style)
constant errorcodes = {"digit expected", -- 1
"')' expected", -- 2
"digit already used", -- 3
"digit not offered", -- 4
"operand expected"} -- 5
function card(integer idx) -- (for error handling)
if idx=1 then return "1st" end if
if idx=2 then return "2nd" end if
-- (assumes expression is less than 21 characters)
return sprintf("%dth",idx)
end function
function errorchar(sequence equation, integer idx)
if idx>length(equation) then return "" end if
return sprintf("(%s)",equation[idx])
end function
sequence rset = repeat(0,4)
procedure new_rset()
for i=1 to length(rset) do
rset[i] = rand(9)
end for
end procedure
function get_operand(string equation, integer idx, sequence unused)
integer ch, k,
error = 1 -- "digit expected"
atom res
if idx<=length(equation) then
ch = equation[idx]
if ch='(' then
{error,res,unused,idx} = eval(equation,unused,idx+1)
if error=0
and idx<=length(equation) then
ch = equation[idx]
if ch=')' then
return {0,res,unused,idx+1}
end if
end if
if error=0 then
error = 2 -- "')' expected"
end if
elsif ch>='0' and ch<='9' then
res = ch-'0'
k = find(res,unused)
if k!=0 then
unused[k..k] = {}
return {0,res,unused,idx+1}
end if
if find(res,rset) then
error = 3 -- "digit already used"
else
error = 4 -- "digit not offered"
end if
end if
end if
return {error,0,unused,idx}
end function
function get_operator(string equation, integer idx)
integer ch, error = 5 -- "operand expected"
if idx<=length(equation) then
ch = equation[idx]
if find(ch,"+-/*") then
return {0,ch,idx+1}
end if
end if
return {error,0,idx}
end function
function eval(string equation, sequence unused, integer idx=1)
atom lhs, rhs
integer ch, error
{error,lhs,unused,idx} = get_operand(equation,idx,unused)
if error=0 then
while 1 do
{error,ch,idx} = get_operator(equation,idx)
if error!=0 then exit end if
{error,rhs,unused,idx} = get_operand(equation,idx,unused)
if error!=0 then exit end if
if ch='+' then lhs += rhs
elsif ch='-' then lhs -= rhs
elsif ch='/' then lhs /= rhs
elsif ch='*' then lhs *= rhs
else ?9/0 -- (should not happen)
end if
if idx>length(equation) then
return {0,lhs,unused,idx}
end if
ch = equation[idx]
if ch=')' then
return {0,lhs,unused,idx}
end if
end while
end if
return {error,0,unused,idx}
end function
function strip(string equation)
for i=length(equation) to 1 by -1 do
if find(equation[i]," \t\r\n") then
equation[i..i] = ""
end if
end for
return equation
end function
function strip0(atom a) -- (for error handling)
string res = sprintf("%f",a)
integer ch
for i=length(res) to 2 by -1 do
ch = res[i]
if ch='.' then return res[1..i-1] end if
if ch!='0' then return res[1..i] end if
end for
return res
end function
procedure play()
sequence unused
string equation
integer error,idx
atom res
new_rset()
printf(1,"Enter an expression which evaluates to exactly 24\n"&
"Use all of, and only, the digits %d, %d, %d, and %d\n"&
"You may only use the operators + - * /\n"&
"Parentheses and spaces are allowed\n",rset)
while 1 do
equation = strip(gets(0))
if upper(equation)="Q" then exit end if
if equation="?" then
puts(1,"\n")
integer r_solve24 = routine_id("solve24") -- see below
if r_solve24=-1 then -- (someone copied just this code out?)
puts(1,"no solve24 routine\n")
else
call_proc(r_solve24,{rset})
end if
else
{error,res,unused,idx} = eval(equation, rset)
if error!=0 then
printf(1," %s on the %s character%s\n",{errorcodes[error],card(idx),errorchar(equation,idx)})
elsif idx<=length(equation) then
printf(1,"\neval() returned only having processed %d of %d characters\n",{idx,length(equation)})
elsif length(unused) then
printf(1," not all the digits were used\n",error)
elsif res!=24 then
printf(1,"\nresult is %s, not 24\n",{strip0(res)})
else
puts(1," correct! Press any key to quit\n")
if getc(0) then end if
exit
end if
end if
puts(1,"enter Q to give up and quit\n")
end while
end procedure
play()

View file

@ -0,0 +1,40 @@
is_num = (s):
x = s ord(0)
if (x >= "0"ord && x <= "9"ord): true.
else: false.
.
nums = (s):
res = ()
0 to (s length, (b):
c = s(b)
if (is_num(c)):
res push(c).
.)
res.
try = 1
while (true):
r = rand string
digits = (r(0),r(1),r(2),r(3))
"\nMy next four digits: " print
digits join(" ") say
digit_s = digits ins_sort string
("Your expression to create 24 (try ", try, "): ") print
entry = read slice(0,-1)
expr = entry eval
parse = nums(entry)
parse_s = parse clone ins_sort string
try++
if (parse length != 4):
("Wrong number of digits:", parse) say.
elsif (parse_s != digit_s):
("Wrong digits:", parse) say.
elsif (expr == 24):
"You won!" say
entry print, " => 24" say
return().
else:
(entry, " => ", expr string, " != 24") join("") say.
.

View file

@ -0,0 +1,36 @@
const digits = (1..9 -> pick(4));
const grammar = Regex.new(
'^ (?&exp) \z
(?(DEFINE)
(?<exp> ( (?&term) (?&op) (?&term) )+ )
(?<term> \( (?&exp) \) | [' + digits.join + '])
(?<op> [-+*/] )
)', 'x'
);
 
say "Here are your digits: #{digits.join(' ')}";
 
loop {
var input = Sys.scanln("Expression: ");
 
var expr = input;
expr -= /\s+/g; # remove all whitespace
 
input == 'q' && (
say "Goodbye. Sorry you couldn't win.";
break;
);
 
var given_digits = digits.map{.to_s}.sort.join;
var entry_digits = input.scan(/\d/).sort.join;
 
if ((given_digits != entry_digits) || (expr !~ grammar)) {
say "That's not valid";
next;
}
 
given(var n = eval(input)) {
when (24) { say "You win!"; break }
default { say "Sorry, your expression is #{n}, not 24" }
}
}

View file

@ -0,0 +1,74 @@
import Darwin
import Foundation
println("24 Game")
println("Generating 4 digits...")
func randomDigits() -> Int[] {
var result = Int[]();
for var i = 0; i < 4; i++ {
result.append(Int(arc4random_uniform(9)+1))
}
return result;
}
// Choose 4 digits
let digits = randomDigits()
print("Make 24 using these digits : ")
for digit in digits {
print("\(digit) ")
}
println()
// get input from operator
var input = NSString(data:NSFileHandle.fileHandleWithStandardInput().availableData, encoding:NSUTF8StringEncoding)
var enteredDigits = Int[]()
var enteredOperations = Character[]()
let inputString = input as String
// store input in the appropriate table
for character in inputString {
switch character {
case "1", "2", "3", "4", "5", "6", "7", "8", "9":
let digit = String(character)
enteredDigits.append(digit.toInt()!)
case "+", "-", "*", "/":
enteredOperations.append(character)
case "\n":
println()
default:
println("Invalid expression")
}
}
// check value of expression provided by the operator
var value = Int()
if enteredDigits.count == 4 && enteredOperations.count == 3 {
value = enteredDigits[0]
for (i, operation) in enumerate(enteredOperations) {
switch operation {
case "+":
value = value + enteredDigits[i+1]
case "-":
value = value - enteredDigits[i+1]
case "*":
value = value * enteredDigits[i+1]
case "/":
value = value / enteredDigits[i+1]
default:
println("This message should never happen!")
}
}
}
if value != 24 {
println("The value of the provided expression is \(value) instead of 24!")
} else {
println("Congratulations, you found a solution!")
}

View file

@ -0,0 +1,89 @@
' version 03-11-2016
' compile with: fbc -s console
#Include Once "gmp.bi"
Sub partitions(max As ULong, p() As MpZ_ptr)
' based on Numericana code example
Dim As ULong a, b, i, k
Dim As Long j
Dim As Mpz_ptr s = Allocate(Len(__mpz_struct)) : Mpz_init(s)
Mpz_set_ui(p(0), 1)
For i = 1 To max
j = 1 : k = 1 : b = 2 : a = 5
While j > 0
' j = i - (3*k*k+k) \ 2
j = i - b : b = b + a : a = a + 3
If j >= 0 Then
If k And 1 Then Mpz_add(s, s, p(j)) Else Mpz_sub(s, s, p(j))
End If
j = j + k
If j >= 0 Then
If k And 1 Then Mpz_add(s, s, p(j)) Else Mpz_sub(s, s, p(j))
End If
k = k +1
Wend
Mpz_swap(p(i), s)
Next
Mpz_clear(s)
End Sub
' ------=< MAIN >=------
Dim As ULong n, k, max = 25 ' with max > 479 the numbers become
Dim As ULongInt p(max, max) ' to big for a 64bit unsigned integer
p(1, 1) = 1 ' fill the first 3 rows
p(2, 1) = 1 : p(2, 2) = 1
p(3, 1) = 1 : p(3, 2) = 1 : p(3, 3) = 1
For n = 4 To max ' fill the rest
For k = 1 To n
If k * 2 > n Then
p(n,k)= p(n-1,k-1)
Else
p(n,k) = p(n-1,k-1) + p(n-k, k)
End If
Next
Next
For n = 1 To 25 ' print the triangle
Print Space((max - n) * 2);
For k = 1 To n
Print Using "####"; p(n, k);
Next
Print
Next
Print : print
' calculate the integer partition
max = 123456 ' 1234567 takes about ten minutes
Dim As ZString Ptr ans
ReDim big_p(max) As Mpz_ptr
For n = 0 To max
big_p(n) = Allocate(Len(__mpz_struct)) : Mpz_init(big_p(n))
Next
partitions(max, big_p())
For n = 1 To Len(Str(max))
k = Val(Left(Str(max), n))
ans = Mpz_get_str (0, 10, big_p(k))
Print Space(10 - n); "P("; Str(k); ") = "; *ans
Next
For n = 0 To max
Mpz_clear(big_p(n))
Next
' empty keyboard buffer
While InKey <> "" : Wend
Print : Print "hit any key to end program"
Sleep
End

View file

@ -0,0 +1,31 @@
define cumu(n::integer) => {
loop(-from=$cache->size,-to=#n+1) => {
local(r = array(0), l = loop_count)
loop(loop_count) => {
protect => { #r->insert(#r->last + $cache->get(#l - loop_count)->get(math_min(loop_count+1, #l - loop_count))) }
}
#r->size > 1 ? $cache->insert(#r)
}
return $cache->get(#n)
}
define row(n::integer) => {
// cache gets reset & rebuilt for each row, slower but more accurate
var(cache = array(array(1)))
local(r = cumu(#n+1))
local(o = array)
loop(#n) => {
protect => { #o->insert(#r->get(loop_count+1) - #r->get(loop_count)) }
}
return #o
}
'rows:\r'
loop(25) => {^
loop_count + ': '+ row(loop_count)->join(' ') + '\r'
^}
'sums:\r'
with x in array(23, 123, 1234) do => {^
var(cache = array(array(1)))
cumu(#x+1)->last
'\r'
^}

View file

@ -0,0 +1,26 @@
import bigints
var cache = @[@[1.initBigInt]]
proc cumu(n): seq[BigInt] =
for l in cache.len .. n:
var r = @[0.initBigInt]
for x in 1..l:
r.add r[r.high] + cache[l-x][min(x, l-x)]
cache.add r
result = cache[n]
proc row(n): seq[BigInt] =
let r = cumu n
result = @[]
for i in 0 .. <n:
result.add r[i+1] - r[i]
echo "rows:"
for x in 1..10:
echo row x
echo "sums:"
for x in [23, 123, 1234, 12345]:
let c = cumu(x)
echo x, " ", c[c.high]

View file

@ -0,0 +1,33 @@
import bigints
var p = @[1.initBigInt]
proc partitions(n): BigInt =
p.add 0.initBigInt
for k in 1..n:
var d = n - k * (3 * k - 1) div 2
if d < 0:
break
if (k and 1) != 0:
p[n] += p[d]
else:
p[n] -= p[d]
d -= k
if d < 0:
break
if (k and 1) != 0:
p[n] += p[d]
else:
p[n] -= p[d]
result = p[p.high]
const ns = [23, 123, 1234, 12345]
for i in 1 .. max(ns):
let p = partitions(i)
if i in ns:
echo i,": ",p

View file

@ -0,0 +1,52 @@
--
-- Phix does not have a bignum library, and I have not attempted any formatting.
-- sum(1234) shows 1.5697879723e+35, not 156978797223733228787865722354959930,
-- and I did not wait to see if sum(12345) would finish. [for sum read cumu[$]]
-- If you want to try plotting things, then demo\arwendemo\demo_curve_fit.exw
-- might get you started.
function min(atom a, atom b)
if a<=b then return a end if
return b
end function
sequence cache = {{1}}
function cumu(integer n)
sequence r
for l=length(cache) to n do
r = {0}
for x=1 to l do
r = append(r,r[-1]+cache[l-x+1][min(x,l-x)+1])
end for
cache = append(cache,r)
end for
return cache[n]
end function
function row(integer n)
sequence r = cumu(n+1)
sequence res = repeat(0,n)
for i=1 to n do
res[i] = r[i+1]-r[i]
end for
return res
end function
constant cx = {23, 123, 1234} --, 12345}
procedure nine_billion_names()
puts(1,"rows:\n")
for x=1 to 25 do
printf(1,"%2d:",x)
?row(x)
end for
puts(1,"sums:\n")
for i=1 to length(cx) do
printf(1,"%2d:",cx[i])
?cumu(cx[i]+1)[$]
end for
if getc(0) then end if
end procedure
nine_billion_names()

View file

@ -0,0 +1,28 @@
var cache = [[1]]
 
func cumu (n) {
for l in range(cache.len, n) {
var r = [0]
l.times { |i|
r << (r[-1] + cache[l-i][min(i, l-i)])
}
cache << r
}
cache[n]
}
 
func row (n) {
var r = cumu(n)
n.of {|i| r[i] - r[i-1] }
}
 
say "rows:"
15.times { |i|
"%2s: %s\n".printf(i, row(i))
}
 
say "\nsums:"
 
for i in [23, 123, 1234, 12345] {
"%2s : %4s\n".printf(i, cumu(i)[-1])
}

View file

@ -0,0 +1,34 @@
var cache = [[1]]
func namesOfGod(n:Int) -> [Int] {
for l in cache.count...n {
var r = [0]
for x in 1...l {
r.append(r[r.count - 1] + cache[l - x][min(x, l-x)])
}
cache.append(r)
}
return cache[n]
}
func row(n:Int) -> [Int] {
let r = namesOfGod(n)
var returnArray = [Int]()
for i in 0...n - 1 {
returnArray.append(r[i + 1] - r[i])
}
return returnArray
}
println("rows:")
for x in 1...25 {
println("\(x): \(row(x))")
}
println("\nsums: ")
for x in [23, 123, 1234, 12345] {
cache = [[1]]
var array = namesOfGod(x)
var numInt = array[array.count - 1]
println("\(x): \(numInt)")
}

View file

@ -0,0 +1,20 @@
\ 99 bottles of beer on the wall:
: allout "no more bottles" ;
: just-one "1 bottle" ;
: yeah! dup . " bottles" ;
[
' allout ,
' just-one ,
' yeah! ,
] var, bottles
: .bottles dup 2 n:min bottles @ swap caseof ;
: .beer .bottles . " of beer" . ;
: .wall .beer " on the wall" . ;
: .take " Take one down and pass it around" . ;
: beers .wall ", " . .beer '; putc cr
n:1- 0 max .take ", " .
.wall '. putc cr drop ;
' beers 1 99 loop- bye

View file

@ -0,0 +1,7 @@
for(Integer i = 99; i=0; i--){
system.debug(i + ' bottles of beer on the wall');
system.debug('\n');
system.debug(i + ' bottles of beer on the wall');
system.debug(i + ' bottles of beer');
system.debug('take one down, pass it around');
}

View file

@ -0,0 +1,10 @@
99→B
While B
Disp B▶Dec," BOTTLES OF","BEER ON THE WALL"
Disp B▶Dec," BOTTLES OF","BEER",i,i
getKeyʳ
Disp "TAKE ONE DOWN",i,"PASS IT AROUND",i
B--
Disp B▶Dec," BOTTLES OF","BEER ON THE WALL",i
getKeyʳ
End

View file

@ -0,0 +1,139 @@
const bottle = " bottle"
const plural = "s"
const ofbeer = " of beer"
const wall = " on the wall"
const sep = ", "
const takedown = "Take one down and pass it around, "
const u_no = "No"
const l_no = "no"
const more = " more bottles of beer"
const store = "Go to the store and buy some more, "
const dotnl = ".\n"
const nl = "\n"
// Print two digits, use the value in a
fun printnum
b = a
loop
break (a < 10)
a /= 10
// modulo is in the d register after idiv
b = d
a += 48 // ASCII value for '0'
print(chr(a))
break
end
a = b
a += 48 // ASCII value for '0'
print(chr(a))
end
fun main
loop 99
// Save loop counter for later, twice
c -> stack
c -> stack
// Print the loop counter (passed in the a register)
a = c
printnum()
// N, "bottles of beer on the wall, "
print(bottle)
print(plural)
print(ofbeer)
print(wall)
print(sep)
// Retrieve and print the number
stack -> a
printnum()
// N, "bottles of beer."
print(bottle)
print(plural)
print(ofbeer)
print(dotnl)
// "Take one down and pass it around,"
print(takedown)
// N-1, "bottles of beer on the wall."
stack -> a
a--
// Store N-1, used just a few lines down
a -> stack
printnum()
print(bottle)
// Retrieve N-1
stack -> a
// Write an "s" if the count is not 1
a != 1
print(plural)
end
// Write the rest
print(ofbeer)
print(wall)
print(dotnl)
// Blank line
print(nl)
// Skip to the top of the loop while the counter is >= 2
continue (c >= 2)
// At the last two
// "1 bottle of beer on the wall,"
a = 1
printnum()
print(bottle)
print(ofbeer)
print(wall)
print(sep)
// "1 bottle of beer."
a = 1
printnum()
print(bottle)
print(ofbeer)
print(dotnl)
// "Take one down and pass it around,"
print(takedown)
// "no more bottles of beer on the wall."
print(l_no)
print(more)
print(wall)
print(dotnl)
// Blank line
print(nl)
// "No more bottles of beer on the wall,"
print(u_no)
print(more)
print(wall)
print(sep)
// "no more bottles of beer."
print(l_no)
print(more)
print(dotnl)
// "Go to the store and buy some more,"
print(store)
// "99 bottles of beer on the wall."
a = 99
printnum()
print(bottle)
print(plural)
print(ofbeer)
print(wall)
print(dotnl)
end
end
// vim: set syntax=c ts=4 sw=4 et:

View file

@ -0,0 +1,13 @@
shared void ninetyNineBottles() {
String bottles(Integer count) =>
"``count == 0 then "No" else count``
bottle``count == 1 then "" else "s"``".normalized;
for(i in 99..1) {
print("``bottles(i)`` of beer on the wall
``bottles(i)`` of beer!
Take one down, pass it around
``bottles(i - 1)`` of beer on the wall!\n");
}
}

View file

@ -0,0 +1,22 @@
Layout := RECORD
UNSIGNED1 RecID1;
UNSIGNED1 RecID2;
STRING30 txt;
END;
Beers := DATASET(99,TRANSFORM(Layout,
SELF.RecID1 := COUNTER,SELF.RecID2 := 0,SELF.txt := ''));
Layout XF(Layout L,INTEGER C) := TRANSFORM
IsOneNext := L.RecID1-1 = 1;
IsOne := L.RecID1 = 1;
SELF.txt := CHOOSE(C,
(STRING)(L.RecID1-1) + ' bottle'+IF(IsOneNext,'','s')+' of beer on the wall',
'Take one down, pass it around',
(STRING)(L.RecID1) + ' bottle'+IF(IsOne,'','s')+' of beer',
(STRING)(L.RecID1) + ' bottle'+IF(IsOne,'','s')+' of beer on the wall','');
SELF.RecID2 := C;
SELF := L;
END;
Rev := NORMALIZE(Beers,5,XF(LEFT,COUNTER));
OUTPUT(SORT(Rev,-Recid1,-RecID2),{txt},ALL);

View file

@ -0,0 +1,30 @@
val
numbers = {1:'one', 2:'two', 3:'three', 4:'four', 5:'five', 6:'six', 7:'seven',
8:'eight', 9:'nine', 10:'ten', 11:'eleven', 12:'twelve'}
alt = {3:'thir', 5:'fif'}
def
suffix( a, b ) = (if a.endsWith( 't' ) then a.substring( 0, a.length()-1 ) else a) + b
number( n@(13 | 15) ) = suffix( alt(n%10), 'teen' )
number( 20 ) = 'twenty'
number( n@(30 | 50) ) = suffix( alt(n\10), 'ty' )
number( n )
| n <= 12 = numbers(n)
| n <= 19 = suffix( numbers(n%10), 'teen' )
| 10|n = suffix( numbers(n\10), 'ty' )
| otherwise = number( n\10*10 ) + '-' + number( n%10 )
cap( s ) = s.substring( 0, 1 ).toUpperCase() + s.substring( 1, s.length() )
bottles( 0 ) = 'no more bottles'
bottles( 1 ) = 'one bottle'
bottles( n ) = number( n ) + ' bottles'
verse( 0 ) = ('No more bottles of beer on the wall, no more bottles of beer.\n'
+ 'Go to the store and buy some more, ninety-nine bottles of beer on the wall.')
verse( n ) = (cap( bottles(n) ) + ' of beer on the wall, ' + bottles( n ) + ' of beer.\n'
+ 'Take one down and pass it around, ' + bottles( n-1 )
+ ' of beer on the wall.\n')
for i <- 99..0 by -1 do println( verse(i) )

View file

@ -0,0 +1,12 @@
include "ConsoleWindow"
dim as short i
for i = 99 to 1 step -1
print i; " bottles of beer on the wall,"
print i; " bottles of beer."
print
print "Take one down, pass it around,"
print i-1; " bottles of beer on the wall."
print
next

View file

@ -0,0 +1,19 @@
beerSong : Fin 100 -> String
beerSong x = verses x where
bottlesOfBeer : Fin n -> String
bottlesOfBeer fZ = "No more bottles of beer"
bottlesOfBeer (fS fZ) = "1 bottle of beer"
bottlesOfBeer k = (show (finToInteger k)) ++ " bottles of beer"
verse : Fin n -> String
verse fZ = ""
verse (fS n) =
(bottlesOfBeer (fS n)) ++ " on the wall,\n" ++
(bottlesOfBeer (fS n)) ++ "\n" ++
"Take one down, pass it around\n" ++
(bottlesOfBeer n) ++ " on the wall\n"
verses : Fin n -> String
verses fZ = ""
verses (fS n) = (verse (fS n)) ++ (verses n)

View file

@ -0,0 +1,19 @@
bottles::{:[x=1;"bottle";"bottles"]}
itone::{:[x=1;"it";"one"]}
numno::{:[x=0;"no";x]}
drink::{.d(numno(x));
.d(" ");
.d(bottles(x));
.p(" of beer on the wall");
.d(numno(x));
.d(" ");
.d(bottles(x));
.p(" of beer");
.d("take ");
.d(itone(x));
.p(" down and pass it round");
.d(numno(x-1));
.d(" ");
.d(bottles(x-1));
.p(" of beer on the wall");.p("")}
drink'1+|!99

View file

@ -0,0 +1,5 @@
sig bottles.
type println string -> o.
type round int -> o.
type bottles_song int -> o.

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