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,249 @@
import Maybe as M
import Result as R
import Matrix
import Mouse
import Random exposing (Seed)
import Matrix.Random
import Time exposing (Time, every, second)
import Set exposing (Set, fromList)
import List exposing (..)
import String exposing (join)
import Html exposing (Html, br, input, h1, h2, text, div, button)
import Html.Events as HE
import Html.Attributes as HA
import Html.App exposing (program)
import Json.Decode as JD
import Svg
import Svg.Attributes exposing (version, viewBox, cx, cy, r, x, y, x1, y1, x2, y2, fill,points, style, width, height, preserveAspectRatio)
minSide = 10
maxSide = 40
w = 700
h = 700
dt = 0.001
type alias Direction = Int
down = 0
right = 1
type alias Door = (Matrix.Location, Direction)
type State = Initial | Generating | Generated | Solved
type alias Model =
{ rows : Int
, cols : Int
, animate : Bool
, boxes : Matrix.Matrix Bool
, doors : Set Door
, current : List Matrix.Location
, state : State
, seedStarter : Int
, seed : Seed
}
initdoors : Int -> Int -> Set Door
initdoors rows cols =
let
pairs la lb = List.concatMap (\at -> List.map ((,) at) lb) la
downs = pairs (pairs [0..rows-2] [0..cols-1]) [down]
rights = pairs (pairs [0..rows-1] [0..cols-2]) [right]
in downs ++ rights |> fromList
initModel : Int -> Int -> Bool -> State -> Int -> Model
initModel rows cols animate state starter =
let rowGenerator = Random.int 0 (rows-1)
colGenerator = Random.int 0 (cols-1)
locationGenerator = Random.pair rowGenerator colGenerator
(c, s)= Random.step locationGenerator (Random.initialSeed starter)
in { rows = rows
, cols = cols
, animate = animate
, boxes = Matrix.matrix rows cols (\location -> state == Generating && location == c)
, doors = initdoors rows cols
, current = if state == Generating then [c] else []
, state = state
, seedStarter = starter -- updated every Tick until maze generated.
, seed = s
}
view model =
let
borderLineStyle = style "stroke:green;stroke-width:0.3"
wallLineStyle = style "stroke:green;stroke-width:0.1"
x1Min = x1 <| toString 0
y1Min = y1 <| toString 0
x1Max = x1 <| toString model.cols
y1Max = y1 <| toString model.rows
x2Min = x2 <| toString 0
y2Min = y2 <| toString 0
x2Max = x2 <| toString model.cols
y2Max = y2 <| toString model.rows
borders = [ Svg.line [ x1Min, y1Min, x2Max, y2Min, borderLineStyle ] []
, Svg.line [ x1Max, y1Min, x2Max, y2Max, borderLineStyle ] []
, Svg.line [ x1Max, y1Max, x2Min, y2Max, borderLineStyle ] []
, Svg.line [ x1Min, y1Max, x2Min, y2Min, borderLineStyle ] []
]
doorToLine door =
let (deltaX1, deltaY1) = if (snd door == right) then (1,0) else (0,1)
(row, column) = fst door
in Svg.line [ x1 <| toString (column + deltaX1)
, y1 <| toString (row + deltaY1)
, x2 <| toString (column + 1)
, y2 <| toString (row + 1)
, wallLineStyle ] []
doors = (List.map doorToLine <| Set.toList model.doors )
circleInBox (row,col) color =
Svg.circle [ r "0.25"
, fill (color)
, cx (toString (toFloat col + 0.5))
, cy (toString (toFloat row + 0.5))
] []
showUnvisited location box =
if box then [] else [ circleInBox location "yellow" ]
unvisited = model.boxes
|> Matrix.mapWithLocation showUnvisited
|> Matrix.flatten
|> concat
current =
case head model.current of
Nothing -> []
Just c -> [circleInBox c "black"]
maze =
if model.animate || model.state /= Generating
then [ Svg.g [] <| doors ++ borders ++ unvisited ++ current ]
else [ Svg.g [] <| borders ]
in
div
[]
[ h2 [centerTitle] [text "Maze Generator"]
, div
[floatLeft]
( slider "rows" minSide maxSide model.rows SetRows
++ [ br [] [] ]
++ slider "cols" minSide maxSide model.cols SetCols
++ [ br [] [] ]
++ checkbox "Animate" model.animate SetAnimate
++ [ br [] [] ]
++ [ button
[ HE.onClick Generate ]
[ text "Generate"]
] )
, div
[floatLeft]
[ Svg.svg
[ version "1.1"
, width (toString w)
, height (toString h)
, viewBox (join " "
[ 0 |> toString
, 0 |> toString
, model.cols |> toString
, model.rows |> toString ])
]
maze
]
]
checkbox label checked msg =
[ input
[ HA.type' "checkbox"
, HA.checked checked
, HE.on "change" (JD.map msg HE.targetChecked)
]
[]
, text label
]
slider name min max current msg =
[ input
[ HA.value (if current >= min then current |> toString else "")
, HE.on "input" (JD.map msg HE.targetValue )
, HA.type' "range"
, HA.min <| toString min
, HA.max <| toString max
]
[]
, text <| name ++ "=" ++ (current |> toString)
]
floatLeft = HA.style [ ("float", "left") ]
centerTitle = HA.style [ ( "text-align", "center") ]
unvisitedNeighbors : Model -> Matrix.Location -> List Matrix.Location
unvisitedNeighbors model (row,col) =
[(row, col-1), (row-1, col), (row, col+1), (row+1, col)]
|> List.filter (\l -> fst l >= 0 && snd l >= 0 && fst l < model.rows && snd l < model.cols)
|> List.filter (\l -> (Matrix.get l model.boxes) |> M.withDefault False |> not)
updateModel' : Model -> Int -> Model
updateModel' model t =
case head model.current of
Nothing -> {model | state = Generated, seedStarter = t }
Just prev ->
let neighbors = unvisitedNeighbors model prev
in if (length neighbors) > 0 then
let (neighborIndex, seed) = Random.step (Random.int 0 (length neighbors-1)) model.seed
next = head (drop neighborIndex neighbors) |> M.withDefault (0,0)
boxes = Matrix.set next True model.boxes
dir = if fst prev == fst next then right else down
doorCell = if ( (dir == down) && (fst prev < fst next))
|| (dir == right ) && (snd prev < snd next) then prev else next
doors = Set.remove (doorCell, dir) model.doors
in {model | boxes=boxes, doors=doors, current=next :: model.current, seed=seed, seedStarter = t}
else
let tailCurrent = tail model.current |> M.withDefault []
in updateModel' {model | current = tailCurrent} t
updateModel : Msg -> Model -> Model
updateModel msg model =
let stringToCellCount s =
let v' = String.toInt s |> R.withDefault minSide
in if v' < minSide then minSide else v'
in case msg of
Tick tf ->
let t = truncate tf
in
if (model.state == Generating) then updateModel' model t
else { model | seedStarter = t }
Generate ->
initModel model.rows model.cols model.animate Generating model.seedStarter
SetRows countString ->
initModel (stringToCellCount countString) model.cols model.animate Initial model.seedStarter
SetCols countString ->
initModel model.rows (stringToCellCount countString) model.animate Initial model.seedStarter
SetAnimate b ->
{ model | animate = b }
NoOp -> model
type Msg = NoOp | Tick Time | Generate | SetRows String | SetCols String | SetAnimate Bool
subscriptions model = every (dt * second) Tick
main =
let
update msg model = (updateModel msg model, Cmd.none)
init = (initModel 21 36 False Initial 0, Cmd.none)
in program
{ init = init
, view = view
, update = update
, subscriptions = subscriptions
}

View file

@ -0,0 +1,130 @@
' version 04-12-2016
' compile with: fbc -s console
' when generating a big maze it's possible to run out of stack space
' increase stack with the -t xxxx (xxxx is the amount you want in Kbytes)
ReDim Shared As String d() ' directions
ReDim Shared As ULong c() ' cell's
Sub cell(x As ULong, y As ULong, s As ULong)
Dim As ULong x1, y1, di_n
c(x,y) = 1 ' mark as visited
Do
Dim As String di = d(x, y)
Dim As Long l = Len(di) -1
If l < 0 Then Exit Sub ' no directions left then exit
di_n = di[l] ' get direction
If l = 0 Then
d(x,y) = ""
Else
d(x,y) = Left(di,l)
End If
Select Case di_n ' 0,0 is upper left corner
Case Asc("N")
x1 = x : y1 = y -1
Case Asc("E")
x1 = x +1 : y1 = y
Case Asc("S")
x1 = x : y1 = y +1
Case Asc("W")
x1 = x -1 : y1 = y
End Select
If c(x1,y1) <> 0 Then Continue Do
Select Case di_n ' 0,0 is upper left corner
Case Asc("N")
Line (x * s +1 , y * s) - ((x +1) * s -1, y * s),0
Case Asc("E")
Line (x1 * s, y * s +1) - (x1 * s, (y +1) * s -1),0
Case Asc("S")
Line (x * s +1, y1 * s) - ((x +1) * s -1, y1 * s),0
Case Asc("W")
Line (x * s , y * s +1) - (x * s, (y +1) * s -1),0
End Select
cell(x1, y1, s)
Loop
End Sub
Sub gen_maze(w As ULong, h As ULong, s As ULong)
ReDim d(w, h)
ReDim c(w, h)
Dim As ULong x, y, r, i
Dim As String di
d(0, 0) = "SE" ' cornes
d(0, h -1) ="NE"
d(w -1, 0) ="SW"
d(w -1, h -1) ="NW"
For x = 1 To w -2 ' sides
d(x,0) = "EWS"
d(x,h -1) = "NEW"
Next
For y = 1 To h -2
d(0, y) = "NSE"
d(w -1, y) ="NSW"
Next
For x = 0 To w -1 ' shuffle directions
For y = 0 To h -1
di = d(x,y)
If di = "" Then di = "NEWS"
i = Len(di)
Do
r = Fix(Rnd * i)
i = i - 1
Swap di[r], di[i]
Loop Until i = 0
d(x,y) = di
Next
Next
ScreenRes w * s +1, h * s +1, 8
' draw the grid
For x = 0 To w
Line (x * s, 0) - (x * s, h * s), 2 ' green color
Next
For y = 0 To h
Line(0, y * s) - (w* s, y * s),2
Next
' choice the start cell
x = Fix(Rnd * w)
y = Fix(Rnd * h)
cell(x, y, s)
End Sub
' ------=< MAIN >=------
Randomize Timer
Dim As ULong t
Do
' gen_maxe(width, height, cell size)
gen_maze(30, 30, 20)
WindowTitle " S to save, N for next maze, other key to stop"
Do
Var key = Inkey
key = UCase(key)
If key = "S" Then
t = t +1
BSave("maze" + Str(t) + ".bmp"), 0
key = ""
End If
If key = "N" Then Continue Do, Do
If key <> "" Then Exit Do, Do
Loop
Loop
End

View file

@ -0,0 +1,37 @@
import math, sequtils, strutils
randomize()
template newSeqWith(len: int, init: expr): expr =
var result {.gensym.} = newSeq[type(init)](len)
for i in 0 .. <len:
result[i] = init
result
iterator randomCover[T](xs: openarray[T]): T =
var js = toSeq 0..xs.high
for i in countdown(js.high, 0):
let j = random(i + 1)
swap(js[i], js[j])
for j in js:
yield xs[j]
const
w = 14
h = 10
var
vis = newSeqWith(h, newSeq[bool](w))
hor = newSeqWith(h+1, newSeqWith(w, "+---"))
ver = newSeqWith(h, newSeqWith(w, "| ") & "|")
proc walk(x, y) =
vis[y][x] = true
for p in [[x-1,y], [x,y+1], [x+1,y], [x,y-1]].randomCover:
if p[0] notin 0 .. <w or p[1] notin 0 .. <h or vis[p[1]][p[0]]: continue
if p[0] == x: hor[max(y, p[1])][x] = "+ "
if p[1] == y: ver[y][max(x, p[0])] = " "
walk p[0], p[1]
walk random(0..w), random(0..h)
for a,b in zip(hor, ver & @[""]).items:
echo join(a & "+\n" & b)

View file

@ -0,0 +1,33 @@
var(w:5, h:5) = ARGV.map{.to_i}...
var avail = (w * h)
# cell is padded by sentinel col and row, so I don't check array bounds
var cell = (1..h -> map {([true] * w) + [false]} + [[false] * w+1])
var ver = (1..h -> map {["| "] * w })
var hor = (0..h -> map {["+--"] * w })
func walk(x, y) {
cell[y][x] = false;
avail-- > 0 || return; # no more bottles, er, cells
var d = [[-1, 0], [0, 1], [1, 0], [0, -1]]
while (!d.is_empty) {
var i = d.pop_rand
var (x1, y1) = (x + i[0], y + i[1])
cell[y1][x1] || next
if (x == x1) { hor[[y1, y].max][x] = '+ ' }
if (y == y1) { ver[y][[x1, x].max] = ' ' }
walk(x1, y1)
}
}
walk(w.rand.int, h.rand.int) # generate
for i in (0 .. h) {
say (hor[i].join('') + '+')
if (i < h) {
say (ver[i].join('') + '|')
}
}

View file

@ -0,0 +1,109 @@
import Foundation
class Direction {
var vect:(Int, Int, Int)
var bit:Int {
let (bit, dx, dy) = vect
return bit
}
var dx:Int {
let (bit, dx, dy) = vect
return dx
}
var dy:Int {
let (bit, dx, dy) = vect
return dy
}
var opposite:Direction {
switch (vect) {
case (1, 0, -1):
return Direction(bit: 2, dx: 0, dy: 1)
case (2, 0, 1):
return Direction(bit: 1, dx: 0, dy: -1)
case (4, 1, 0):
return Direction(bit: 8, dx: -1, dy: 0)
case (8, -1, 0):
return Direction(bit: 4, dx: 1, dy: 0)
default:
return Direction(bit: 0, dx: 0, dy: 0)
}
}
init(bit:Int, dx:Int, dy:Int) {
self.vect = (bit, dx, dy)
}
}
let N = Direction(bit: 1, dx: 0, dy: -1)
let S = Direction(bit: 2, dx: 0, dy: 1)
let E = Direction(bit: 4, dx: 1, dy: 0)
let W = Direction(bit: 8, dx: -1, dy: 0)
class MazeGenerator {
let x:Int!
let y:Int!
var maze:[[Int]]!
init(_ x:Int, _ y:Int) {
self.x = x
self.y = y
var col = [Int](count: y, repeatedValue: 0)
self.maze = [[Int]](count: x, repeatedValue: col)
generateMaze(0, 0)
}
func display() {
for i in 0..<y {
// Draw top edge
for j in 0..<x {
print((maze[j][i] & 1) == 0 ? "+---" : "+ ")
}
println("+")
// Draw left edge
for j in 0..<x {
print((maze[j][i] & 8) == 0 ? "| " : " ")
}
println("|")
}
// Draw bottom edge
for j in 0..<x {
print("+---")
}
println("+")
}
func generateMaze(cx:Int, _ cy:Int) {
var dirs = [N, S, E, W] as NSMutableArray
for i in 0..<dirs.count {
let x1 = Int(arc4random()) % dirs.count
let x2 = Int(arc4random()) % dirs.count
dirs.exchangeObjectAtIndex(x1, withObjectAtIndex: x2)
}
for dir in dirs {
var dir = dir as Direction
let nx = cx + dir.dx
let ny = cy + dir.dy
if (between(nx, self.x) && between(ny, self.y) && (maze[nx][ny] == 0)) {
maze[cx][cy] |= dir.bit
maze[nx][ny] |= dir.opposite.bit
generateMaze(nx, ny)
}
}
}
func between(v:Int, _ upper:Int) -> Bool {
return (v >= 0) && (v < upper)
}
}
let x = 10
let y = 10
let maze = MazeGenerator(x, y)
maze.display()