Last active
February 29, 2016 23:26
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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