Skip to content

Instantly share code, notes, and snippets.

@SpaceAntelope
Last active February 29, 2016 23:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SpaceAntelope/073eebf71a7a29bab333 to your computer and use it in GitHub Desktop.
Save SpaceAntelope/073eebf71a7a29bab333 to your computer and use it in GitHub Desktop.
A bit of a roundabout sort of way of turning a matrix to a set of obliques, and then turning it back to a matrix again
type ObliqueKind = Wide | Tall | Square
let (|FirstGreater|FirstLesser|BothEqual|) = function 1 -> FirstGreater | -1 -> FirstLesser | 0 -> BothEqual
let ParseTextInput (input : string ) =
input.Split('\n')
|> Array.where (fun line -> System.String.IsNullOrEmpty(line) |> not )
|> Array.map (fun line -> System.Text.RegularExpressions.Regex.Split(line.Trim(),"\s+") |> Array.map(int))
let TraceObliqueFromStartingPoint rowCount (rowIndex,colIndex) =
let maxVerticalLength = rowCount - rowIndex - 1
let maxHorizontalLength = colIndex
match maxVerticalLength.CompareTo(maxHorizontalLength) with
| FirstGreater -> List.zip [rowIndex..(rowCount-1)].[..maxHorizontalLength] [colIndex..(-1)..0]
| FirstLesser -> List.zip [rowIndex..(rowCount-1)] [colIndex..(-1)..0].[..maxVerticalLength]
| BothEqual -> List.zip [rowIndex..(rowCount-1)] [colIndex..(-1)..0]
let TraceObliquesStartingPoints rowCount colCount =
let (|MovingAccrossTopEdge|MovingAccrossRightEdge|BottomRightCorner|Other|) (row, col) =
if col < colCount-1 then MovingAccrossTopEdge
elif col = colCount-1 && row < rowCount then MovingAccrossRightEdge
elif col = colCount-1 && row = rowCount-1 then BottomRightCorner
else Other
let rec nextInPath (rowIndex, colIndex) =
match rowIndex, colIndex with
| BottomRightCorner | Other -> []
| MovingAccrossTopEdge -> (rowIndex, colIndex) ::nextInPath(rowIndex,colIndex+1)
| MovingAccrossRightEdge -> (rowIndex, colIndex) ::nextInPath(rowIndex+1,colIndex)
nextInPath (0,0)
let Obliques input =
let table = ParseTextInput input
let (rowCount,colCount) = table.Length, table.[0].Length
TraceObliquesStartingPoints rowCount colCount
|> List.map(TraceObliqueFromStartingPoint rowCount)
|> List.map (List.map (fun (rowIndex,colIndex)-> table.[rowIndex].[colIndex]))
let Deoblique (input:int list list) (kind: ObliqueKind) =
let deobliqueBySize (input:int list list) rowCount colCount =
let result = Array.init rowCount (fun _ -> Array.init colCount (fun _ -> 0) )
// Generate oblique coordinates
TraceObliquesStartingPoints rowCount colCount
|> List.map(TraceObliqueFromStartingPoint rowCount)
// Combine them with the oblique values from the input
|> List.zip input
// Make the resulting structure a bit more wieldy
// ( at this point the type is (int list * (int * int) list) list)
|> List.map (fun (values, coords)-> List.zip values coords)
|> List.concat
// Fill the preinitialized table
|> List.iter(fun (value,(rowIndex,colIndex))-> result.[rowIndex].[colIndex] <- value)
result
let maxLength = input |> List.map(fun ob->ob.Length) |> List.max
let tableLength = input |> List.countBy(fun ob->ob.Length=maxLength) |> List.last |> snd |> (+) (maxLength-1)
match kind with
| Square -> deobliqueBySize input maxLength maxLength
| Tall -> deobliqueBySize input tableLength maxLength
| Wide -> deobliqueBySize input maxLength tableLength
let printList lst =
List.iter(printf "%A\t") lst
printfn ""
let printArray arr =
Array.iter(printf "%A\t") arr
printfn ""
let Example input kind =
let obs = Obliques input
printfn "%A obliques:" kind
obs |> List.iter (printList)
let deobs = Deoblique obs kind
printfn "%A input from obliques:" kind
deobs |> Array.iter (printArray)
printfn ""
let tallInput = @"
0 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"
let wideInput = @"
0 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"
let squareInput = @"
0 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"
Example tallInput Tall
Example wideInput Wide
Example squareInput Square
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment