3 people like it.

Print a list in a spiral

Prints a list in a spiral

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
27: 
28: 
29: 
30: 
31: 
32: 
33: 
34: 
35: 
36: 
37: 
38: 
39: 
40: 
41: 
42: 
43: 
44: 
45: 
46: 
47: 
48: 
49: 
50: 
51: 
52: 
53: 
54: 
55: 
56: 
57: 
58: 
59: 
60: 
61: 
62: 
63: 
64: 
65: 
66: 
67: 
68: 
69: 
70: 
71: 
72: 
73: 
74: 
75: 
76: 
module CircularPrint

open FsUnit
open NUnit.Framework

type Direction = int * int -> int * int

type Directions = Direction []

let right (x,y) = (x + 1, y)
let down  (x,y) = (x, y + 1)
let left  (x,y) = (x - 1, y)
let up    (x,y) = (x, y - 1)

let directions : Directions = [| right; down; left; up; |]

let board n = 
    let count = ref 0
    Array2D.init n n (fun x y -> count := !count + 1; !count)
     
let printBoard (directions : Directions) (board: int[,]) = 
    seq {
        let (@) (twoDArr : 'a[,]) (x,y) = twoDArr.[y,x]

        let length = Array2D.length1 board

        let rec print pos moveNum bound =         
            seq{               
       
                let boundsCheck (x, y) = 
                    let ``end`` = length - bound 
                    let start = bound
       
                    x < ``end`` && y < ``end`` && x >= start && y >= start

                let direction n = directions.[n % (length - 1)]

                let move = moveNum |> direction 
        
                if boundsCheck pos then 
                    yield board @ pos 
                
                let next = pos |> move 
                            
                // go till the next guy hits the past bound
                if boundsCheck next then                    
                    yield! print next moveNum bound

                // if the next goes beyond the bound, shift directions on the original
                // until we've moved N times, covering all elements of the board
                else if moveNum < length then

                    yield! print pos (moveNum + 1) bound    
            }       

        for layer in 0.. Array2D.length1 board do
            yield! print (layer, layer) 0 layer
    } |> Seq.distinct


[<Test>]
let testSquare4 () =     
    board 4
        |> printBoard directions
        |> Seq.toList
        |> should equal [1; 2; 3; 4; 8; 12; 16; 15; 14; 13; 6; 7; 11; 10]


[<Test>]
let testSquare5 () = 
    
    board 5
        |> printBoard directions
        |> Seq.toList
        |> should equal [1; 2; 3; 4; 5; 10; 15; 20; 25; 24; 23; 22; 21; 16; 11; 6; 7; 8; 9; 14; 19; 18; 17; 12; 13]
       
module CircularPrint
namespace FsUnit
namespace NUnit
namespace NUnit.Framework
type Direction = int * int -> int * int

Full name: CircularPrint.Direction
Multiple items
val int : value:'T -> int (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.Operators.int

--------------------
type int = int32

Full name: Microsoft.FSharp.Core.int

--------------------
type int<'Measure> = int

Full name: Microsoft.FSharp.Core.int<_>
type Directions = Direction []

Full name: CircularPrint.Directions
val right : x:int * y:'a -> int * 'a

Full name: CircularPrint.right
val x : int
val y : 'a
val down : x:'a * y:int -> 'a * int

Full name: CircularPrint.down
val x : 'a
val y : int
val left : x:int * y:'a -> int * 'a

Full name: CircularPrint.left
val up : x:'a * y:int -> 'a * int

Full name: CircularPrint.up
val directions : Directions

Full name: CircularPrint.directions
val board : n:int -> int [,]

Full name: CircularPrint.board
val n : int
val count : int ref
Multiple items
val ref : value:'T -> 'T ref

Full name: Microsoft.FSharp.Core.Operators.ref

--------------------
type 'T ref = Ref<'T>

Full name: Microsoft.FSharp.Core.ref<_>
module Array2D

from Microsoft.FSharp.Collections
val init : length1:int -> length2:int -> initializer:(int -> int -> 'T) -> 'T [,]

Full name: Microsoft.FSharp.Collections.Array2D.init
val printBoard : directions:Directions -> board:int [,] -> seq<int>

Full name: CircularPrint.printBoard
val directions : Directions
val board : int [,]
Multiple items
val seq : sequence:seq<'T> -> seq<'T>

Full name: Microsoft.FSharp.Core.Operators.seq

--------------------
type seq<'T> = System.Collections.Generic.IEnumerable<'T>

Full name: Microsoft.FSharp.Collections.seq<_>
val twoDArr : 'a [,]
val length : int
val length1 : array:'T [,] -> int

Full name: Microsoft.FSharp.Collections.Array2D.length1
val print : (int * int -> int -> int -> seq<int>)
val pos : int * int
val moveNum : int
val bound : int
val boundsCheck : (int * int -> bool)
val start : int
val direction : (int -> Direction)
val move : Direction
val next : int * int
val layer : int
module Seq

from Microsoft.FSharp.Collections
val distinct : source:seq<'T> -> seq<'T> (requires equality)

Full name: Microsoft.FSharp.Collections.Seq.distinct
Multiple items
type TestAttribute =
  inherit Attribute
  new : unit -> TestAttribute
  member Description : string with get, set

Full name: NUnit.Framework.TestAttribute

--------------------
TestAttribute() : unit
val testSquare4 : unit -> unit

Full name: CircularPrint.testSquare4
val toList : source:seq<'T> -> 'T list

Full name: Microsoft.FSharp.Collections.Seq.toList
val should : f:('a -> #Constraints.Constraint) -> x:'a -> y:obj -> unit

Full name: FsUnit.TopLevelOperators.should
val equal : x:'a -> EqualsConstraint

Full name: FsUnit.TopLevelOperators.equal
val testSquare5 : unit -> unit

Full name: CircularPrint.testSquare5
Raw view Test code New version

More information

Link:http://fssnip.net/mt
Posted:10 years ago
Author:devshorts
Tags: list