Last active
September 21, 2017 16:09
-
-
Save wokalski/d2e094c41cf2a4f2a46268630ec2cb2f to your computer and use it in GitHub Desktop.
A reordering algorithm
This file contains hidden or 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
let stringByMovingChar c x => Char.(escaped (chr @@ code c + x)); | |
let trimFirst x => String.sub x 1 (String.length x - 1); | |
let rec orderAfter x => | |
switch x { | |
| "" => "1" | |
| _ => | |
switch x.[0] { | |
| '9' => "9" ^ orderAfter (trimFirst x) | |
| c => stringByMovingChar c 1 | |
} | |
}; | |
let rec orderBefore x => | |
switch x { | |
| "" => "" | |
| _ => | |
switch x.[0] { | |
| '0' => "0" ^ orderBefore (trimFirst x) | |
| '1' => "01" | |
| c => stringByMovingChar c (-1) | |
} | |
}; | |
let rec orderBetween prevOrder nextOrder => { | |
let nextLength = String.length nextOrder; | |
let prevLength = String.length prevOrder; | |
if (prevLength == 0) { | |
if (nextLength == 0) { | |
"1" | |
} else { | |
orderBefore nextOrder | |
} | |
} else if ( | |
nextLength == 0 | |
) { | |
orderAfter prevOrder | |
} else if ( | |
Char.code prevOrder.[0] < Char.code nextOrder.[0] - 1 | |
) { | |
stringByMovingChar prevOrder.[0] 1 | |
} else { | |
Char.escaped prevOrder.[0] ^ orderBetween (trimFirst prevOrder) (trimFirst nextOrder) | |
} | |
}; | |
let setOrderBefore nextOrder x => setOrder x (orderBefore nextOrder); | |
let setOrderBetween prevOrder nextOrder x => setOrder x (orderBetween prevOrder nextOrder); | |
let setOrderAfter prevOrder x => setOrder x (orderAfter prevOrder); | |
let move from target l => { | |
let rec revReorderList l head mid tail from target index => | |
switch l { | |
| [x, ...t] => | |
if (index == target || index == from) { | |
revReorderList t head [x, ...mid] tail from target (index + 1) | |
} else if ( | |
index > target | |
) { | |
revReorderList t head mid [x, ...tail] from target (index + 1) | |
} else { | |
revReorderList t [x, ...head] mid tail from target (index + 1) | |
} | |
| [] => | |
let tail = List.rev tail; | |
let mid = | |
if (target < from) { | |
switch (head, mid) { | |
| ([], []) => [] | |
| (_, [_]) => mid | |
| ([], [p, m]) => [setOrderBefore (getOrder m) p, m] | |
| ([h, ..._], [x, y]) => [setOrderBetween (getOrder h) (getOrder y) x, y] | |
| (_, _) => mid | |
} | |
} else { | |
switch (mid, tail) { | |
| ([], []) => [] | |
| ([_], _) => mid | |
| ([p, m], []) => [p, setOrderAfter (getOrder p) m] | |
| ([x, y], [h, ..._]) => [x, setOrderBetween (getOrder x) (getOrder h) y] | |
| (_, _) => mid | |
} | |
}; | |
List.append (List.append (List.rev head) mid) tail | |
}; | |
if (from != target) { | |
revReorderList l [] [] [] from target 0 | |
} else { | |
l | |
} | |
}; | |
type update = | |
| ReorderSource int int; | |
let reduceUpdate project::(project: t) ::update => | |
switch update { | |
| ReorderSource from target => {...project, sources: move from target project.sources} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment