September 2017 Update

This commit is contained in:
Ingy döt Net 2017-09-23 10:01:46 +02:00
parent bba7bfd280
commit ba8067c3b7
14570 changed files with 153136 additions and 63871 deletions

View file

@ -1,7 +1,10 @@
import Data.Array
import Data.List
import Control.Monad
import System.Random
import Data.List (intersperse)
import System.Random (randomRIO)
import Data.Array (Array, (!), (//), array, bounds)
import Control.Monad (zipWithM_, replicateM, foldM, when)
type Board = Array (Char, Char) Int
@ -9,86 +12,104 @@ flp :: Int -> Int
flp 0 = 1
flp 1 = 0
numRows, numCols :: Board -> [Char]
numRows t = let ((a, _), (b, _)) = bounds t in [a .. b]
numRows, numCols :: Board -> String
numRows t =
let ((a, _), (b, _)) = bounds t
in [a .. b]
numCols t = let ((_, a), (_, b)) = bounds t in [a .. b]
numCols t =
let ((_, a), (_, b)) = bounds t
in [a .. b]
flipRow, flipCol :: Board -> Char -> Board
flipRow t r = let e = [ (ix, flp (t ! ix)) | ix <-
zip (repeat r) (numCols t) ]
in t // e
flipRow t r =
let e =
[ (ix, flp (t ! ix))
| ix <- zip (repeat r) (numCols t) ]
in t // e
flipCol t c = let e = [ (ix, flp (t ! ix)) | ix <-
zip (numRows t) (repeat c) ]
in t // e
flipCol t c =
let e =
[ (ix, flp (t ! ix))
| ix <- zip (numRows t) (repeat c) ]
in t // e
printBoard :: Board -> IO ()
printBoard t = do
let rows = numRows t
cols = numCols t
f 0 = '0'
f 1 = '1'
p r xs = putStrLn $ [r, ' '] ++ intersperse ' ' (map f xs)
putStrLn $ " " ++ intersperse ' ' cols
zipWithM_ p rows [ [ t ! (y, x) | x <- cols ] | y <- rows ]
let rows = numRows t
cols = numCols t
f 0 = '0'
f 1 = '1'
p r xs = putStrLn $ [r, ' '] ++ intersperse ' ' (map f xs)
putStrLn $ " " ++ intersperse ' ' cols
zipWithM_
p
rows
[ [ t ! (y, x)
| x <- cols ]
| y <- rows ]
-- create a random goal board, and flip rows and columns randomly
-- to get a starting board
setupGame :: Char -> Char -> IO (Board, Board)
setupGame sizey sizex = do
-- random cell value at (row, col)
let mk rc = fmap (\v -> (rc, v)) $ randomRIO (0, 1)
rows = ['a' .. sizey]
cols = ['1' .. sizex]
goal <- fmap (array (('a', '1'), (sizey, sizex))) $
mapM mk [ (r, c) | r <- rows, c <- cols ]
start <- do
let change :: Board -> Int -> IO Board
-- flip random row
change t 0 = fmap (flipRow t) $ randomRIO ('a', sizey)
-- flip random col
change t 1 = fmap (flipCol t) $ randomRIO ('1', sizex)
numMoves <- randomRIO (3, 15) -- how many flips (3 - 15)
-- determine if rows or cols are flipped
moves <- replicateM numMoves $ randomRIO (0, 1)
-- make changes and get a starting board
foldM change goal moves
if goal /= start -- check if boards are different
then return (goal, start) -- all ok, return both boards
else setupGame sizey sizex -- try again
setupGame sizey sizex
-- random cell value at (row, col)
= do
let mk rc = (\v -> (rc, v)) <$> randomRIO (0, 1)
rows = ['a' .. sizey]
cols = ['1' .. sizex]
goal <-
array (('a', '1'), (sizey, sizex)) <$>
mapM
mk
[ (r, c)
| r <- rows
, c <- cols ]
start <-
do let change :: Board -> Int -> IO Board
-- flip random row
change t 0 = flipRow t <$> randomRIO ('a', sizey)
-- flip random col
change t 1 = flipCol t <$> randomRIO ('1', sizex)
numMoves <- randomRIO (3, 15) -- how many flips (3 - 15)
-- determine if rows or cols are flipped
moves <- replicateM numMoves $ randomRIO (0, 1)
-- make changes and get a starting board
foldM change goal moves
if goal /= start -- check if boards are different
then return (goal, start) -- all ok, return both boards
else setupGame sizey sizex -- try again
main :: IO ()
main = do
putStrLn "Select a board size (1 - 9).\nPress any other key to exit."
sizec <- getChar
when (sizec `elem` ['1' .. '9']) $ do
let size = read [sizec] - 1
(g, s) <- setupGame (['a'..] !! size) (['1'..] !! size)
turns g s 0
where
turns goal current moves = do
putStrLn "\nGoal:"
printBoard goal
putStrLn "\nBoard:"
printBoard current
when (moves > 0) $
putStrLn $ "\nYou've made " ++ show moves ++ " moves so far."
putStrLn $ "\nFlip a row (" ++ numRows current ++
") or a column (" ++ numCols current ++ ")"
v <- getChar
if v `elem` numRows current
then check $ flipRow current v
else if v `elem` numCols current
then check $ flipCol current v
else tryAgain
where check t = if t == goal
then putStrLn $ "\nYou've won in " ++
show (moves + 1) ++ " moves!"
else turns goal t (moves + 1)
tryAgain = do
putStrLn ": Invalid row or column."
turns goal current moves
putStrLn "Select a board size (1 - 9).\nPress any other key to exit."
sizec <- getChar
when (sizec `elem` ['1' .. '9']) $
do let size = read [sizec] - 1
(g, s) <- setupGame (['a' ..] !! size) (['1' ..] !! size)
turns g s 0
where
turns goal current moves = do
putStrLn "\nGoal:"
printBoard goal
putStrLn "\nBoard:"
printBoard current
when (moves > 0) $
putStrLn $ "\nYou've made " ++ show moves ++ " moves so far."
putStrLn $
"\nFlip a row (" ++
numRows current ++ ") or a column (" ++ numCols current ++ ")"
v <- getChar
if v `elem` numRows current
then check $ flipRow current v
else if v `elem` numCols current
then check $ flipCol current v
else tryAgain
where
check t =
if t == goal
then putStrLn $ "\nYou've won in " ++ show (moves + 1) ++ " moves!"
else turns goal t (moves + 1)
tryAgain = do
putStrLn ": Invalid row or column."
turns goal current moves

View file

@ -0,0 +1,92 @@
// version 1.1.3
import java.util.Random
val rand = Random()
val target = Array(3) { IntArray(3) { rand.nextInt(2) } }
val board = Array(3) { IntArray(3) }
fun flipRow(r: Int) {
for (c in 0..2) board[r][c] = if (board[r][c] == 0) 1 else 0
}
fun flipCol(c: Int) {
for (r in 0..2) board[r][c] = if (board[r][c] == 0) 1 else 0
}
/** starting from the target we make 9 random row or column flips */
fun initBoard() {
for (i in 0..2) {
for (j in 0..2) board[i][j] = target[i][j]
}
repeat(9) {
val rc = rand.nextInt(2)
if (rc == 0)
flipRow(rand.nextInt(3))
else
flipCol(rand.nextInt(3))
}
}
fun printBoard(label: String, isTarget: Boolean = false) {
val a = if (isTarget) target else board
println("$label:")
println(" | a b c")
println("---------")
for (r in 0..2) {
print("${r + 1} |")
for (c in 0..2) print(" ${a[r][c]}")
println()
}
println()
}
fun gameOver(): Boolean {
for (r in 0..2) {
for (c in 0..2) if (board[r][c] != target[r][c]) return false
}
return true
}
fun main(args: Array<String>) {
// initialize board and ensure it differs from the target i.e. game not already over!
do {
initBoard()
}
while(gameOver())
printBoard("TARGET", true)
printBoard("OPENING BOARD")
var flips = 0
do {
var isRow = true
var n = -1
do {
print("Enter row number or column letter to be flipped: ")
val input = readLine()!!
val ch = if (input.isNotEmpty()) input[0].toLowerCase() else '0'
if (ch !in "123abc") {
println("Must be 1, 2, 3, a, b or c")
continue
}
if (ch in '1'..'3') {
n = ch.toInt() - 49
}
else {
isRow = false
n = ch.toInt() - 97
}
}
while (n == -1)
flips++
if (isRow) flipRow(n) else flipCol(n)
val plural = if (flips == 1) "" else "S"
printBoard("\nBOARD AFTER $flips FLIP$plural")
}
while (!gameOver())
val plural = if (flips == 1) "" else "s"
println("You've succeeded in $flips flip$plural")
}

View file

@ -0,0 +1,95 @@
target, board, moves, W, H = {}, {}, 0, 3, 3
function getIndex( i, j ) return i + j * W - W end
function flip( d, r )
function invert( a ) if a == 1 then return 0 end return 1 end
local idx
if d == 1 then
for i = 1, W do
idx = getIndex( i, r )
board[idx] = invert( board[idx] )
end
else
for i = 1, H do
idx = getIndex( r, i )
board[idx] = invert( board[idx] )
end
end
moves = moves + 1
end
function createTarget()
target, board = {}, {}
local idx
for j = 1, H do
for i = 1, W do
idx = getIndex( i, j )
if math.random() < .5 then target[idx] = 0
else target[idx] = 1
end
board[idx] = target[idx]
end
end
for i = 1, 103 do
if math.random() < .5 then flip( 1, math.random( H ) )
else flip( 2, math.random( W ) )
end
end
moves = 0
end
function getUserInput()
io.write( "Input row and/or column: " ); local r = io.read()
local a
for i = 1, #r do
a = string.byte( r:sub( i, i ):lower() )
if a >= 48 and a <= 57 then flip( 2, a - 48 ) end
if a >= 97 and a <= string.byte( 'z' ) then flip( 1, a - 96 ) end
end
end
function solved()
local idx
for j = 1, H do
for i = 1, W do
idx = getIndex( i, j )
if target[idx] ~= board[idx] then return false end
end
end
return true
end
function display()
local idx
io.write( "\nTARGET\n " )
for i = 1, W do io.write( string.format( "%d ", i ) ) end; print()
for j = 1, H do
io.write( string.format( "%s ", string.char( 96 + j ) ) )
for i = 1, W do
idx = getIndex( i, j )
io.write( string.format( "%d ", target[idx] ) )
end; io.write( "\n" )
end
io.write( "\nBOARD\n " )
for i = 1, W do io.write( string.format( "%d ", i ) ) end; print()
for j = 1, H do
io.write( string.format( "%s ", string.char( 96 + j ) ) )
for i = 1, W do
idx = getIndex( i, j )
io.write( string.format( "%d ", board[idx] ) )
end; io.write( "\n" )
end
io.write( string.format( "Moves: %d\n", moves ) )
end
function play()
while true do
createTarget()
repeat
display()
getUserInput()
until solved()
display()
io.write( "Very well!\nPlay again(Y/N)? " );
if io.read():lower() ~= "y" then return end
end
end
--[[entry point]]--
math.randomseed( os.time() )
play()

View file

@ -39,7 +39,7 @@ sub build (%hash) {
my $string = ' ';
$string ~= sprintf "%2s ", $_ for sort keys %hash{'1'};
$string ~= "\n";
for sort keys %hash -> $key {
for %hash.keys.sort: +* -> $key {
$string ~= sprintf "%2s ", $key;
$string ~= sprintf "%2s ", %hash{$key}{$_} for sort keys %hash{$key};
$string ~= "\n";
@ -49,6 +49,6 @@ sub build (%hash) {
sub scramble(%hash) {
my @keys = keys %hash;
@keys ,= keys %hash{'1'};
@keys.push: | keys %hash{'1'};
flip $_, %hash for @keys.pick( @keys/2 );
}

View file

@ -1,16 +1,14 @@
/*REXX program presents a "flipping bit" puzzle. The user can solve via it via C.L. */
parse arg N u on off . /*get optional arguments from the C.L. */
parse arg N u . /*get optional arguments from the C.L. */
if N=='' | N=="," then N =3 /*Size given? Then use default of 3.*/
if u=='' | u=="," then u =N /*the number of bits initialized to ON.*/
if on =='' then on =1 /*the character used for "on". */
if off=='' then off=0 /* " " " " "off". */
col@= 'a b c d e f g h i j k l m n o p q r s t u v w x y z' /*for the column id.*/
cols=space(col@,0); upper cols /*letters to be used for the columns. */
@.=off; !.=off /*set both arrays to "off" characters.*/
cols=space(col@, 0); upper cols /*letters to be used for the columns. */
@.=0; !.=0 /*set both arrays to "off" characters.*/
tries=0 /*number of player's attempts (so far).*/
do while show(0) < u /* [↓] turn "on" U number of bits.*/
r=random(1,N); c=random(1,N) /*get a random row and column. */
@.r.c=on ; !.r.c=on /*set (both) row and column to ON. */
r=random(1, N); c=random(1, N) /*get a random row and column. */
@.r.c=1 ; !.r.c=1 /*set (both) row and column to ON. */
end /*while*/ /* [↑] keep going 'til U bits set.*/
oz=z /*keep the original array string. */
call show 1, ' target' /*show target for user to attain. */
@ -19,11 +17,11 @@ call show 1, ' ◄───target' /*show target for user
call flip 'C',random(1,N) /* " " column " " */
end /*random···*/ /* [↑] just perform 1 or 2 times. */
if z==oz then call flip 'R',random(1,N) /*ensure it's not target we're flipping*/
if z==oz then call flip 'R', random(1, N) /*ensure it's not target we're flipping*/
do until z==oz /*prompt until they get it right. */
call prompt /*get a row or column number from C.L. */
call flip left(?,1),substr(?,2) /*flip a user selected row or column. */
call flip left(?, 1), substr(?, 2) /*flip a user selected row or column. */
call show 0 /*get image (Z) of the updated array. */
end /*until···*/
@ -32,13 +30,13 @@ say '─────────Congrats! You did it in' tries "tries
exit tries /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
halt: say 'program was halted!'; exit /*the REXX program was halted by user. */
isInt: return datatype(arg(1),'W') /*returns 1 if arg is an integer.*/
isLet: return datatype(arg(1),'M') /*returns 1 if arg is a letter. */
isInt: return datatype(arg(1), 'W') /*returns 1 if arg is an integer.*/
isLet: return datatype(arg(1), 'M') /*returns 1 if arg is a letter. */
terr: if ok then say '***error!***: illegal' arg(1); ok=0; return
/*──────────────────────────────────────────────────────────────────────────────────────*/
flip: parse arg x,# /*X is R or C; #: is which one.*/
do c=1 for N while x=='R'; if @.#.c==on then @.#.c=off; else @.#.c=on; end
do r=1 for N while x=='C'; if @.r.#==on then @.r.#=off; else @.r.#=on; end
do c=1 for N while x=='R'; @.#.c=\@.#.c; end /*c*/
do r=1 for N while x=='C'; @.r.#=\@.r.#; end /*r*/
return /* [↑] the bits can be ON or OFF. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
prompt: if tries\==0 then say 'bit array after play: ' tries
@ -47,7 +45,7 @@ prompt: if tries\==0 then say '─────────bit array after play
call show 1, ' your array' /*display the array to the terminal. */
do forever; ok=1; say; say !; pull ? _ . 1 all /*prompt & get ans*/
if abbrev('QUIT',?,1) then do; say 'quitting···'; exit 0; end
if abbrev('QUIT', ?, 1) then do; say 'quitting···'; exit 0; end
if ?=='' then do; call show 1," ◄───target",.; ok=0
call show 1," ◄───your array"
end /* [↑] reshow targ*/
@ -56,7 +54,7 @@ prompt: if tries\==0 then say '─────────bit array after play
if isLet(?) then a=pos(?,cols)
if isLet(?) & (a<1 | a>N) then call terr 'column: ' ?
if isLet(?) & length(?)>1 then call terr 'column: ' ?
if isLet(?) then ?='C'pos(?,cols)
if isLet(?) then ?='C'pos(?, cols)
if isInt(?) & (?<1 | ?>N) then call terr 'row: ' ?
if isInt(?) then ?=?/1 /*normalize number*/
if isInt(?) then ?='R'?
@ -66,20 +64,19 @@ prompt: if tries\==0 then say '─────────bit array after play
tries=tries+1 /*bump da counter.*/
return ? /*return response.*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
show: $=0; _=; z=; parse arg tell,tx,o /*$: # of ON bits.*/
show: $=0; _=; parse arg tell,tx,o /*$≡num of ON bits*/
if tell then do; say /*are we telling? */
say ' ' subword(col@,1,N) " column letter"
say 'row 'copies('',N+N+1) /*prepend col hdrs*/
end /* [↑] grid hdrs.*/
z= /* [↓] build grid.*/
do r=1 for N /*show grid rows.*/
do c=1 for N /*build grid cols.*/
if o==. then do; z=z || !.r.c; _=_ !.r.c; $=$+(!.r.c==on); end
else do; z=z || @.r.c; _=_ @.r.c; $=$+(@.r.c==on); end
do c=1 for N; if o==. then do; z=z || !.r.c; _=_ !.r.c; $=$+!.r.c; end
else do; z=z || @.r.c; _=_ @.r.c; $=$+@.r.c; end
end /*c*/ /*··· and sum ONs.*/
if tx\=='' then tar.r=_ tx /*build da target?*/
if tell then say right(r,2) ' '_ tx; _= /*show the grid? */
if tell then say right(r, 2) ' '_ tx; _= /*show the grid? */
end /*r*/ /*show a grid row.*/
if tell then say /*show blank line.*/
return $ /*$: # of ON bits.*/
return $ /*num of on bits. */