Skip to content

Instantly share code, notes, and snippets.

@wokalski
Last active September 21, 2017 16:09
Show Gist options
  • Save wokalski/d2e094c41cf2a4f2a46268630ec2cb2f to your computer and use it in GitHub Desktop.
Save wokalski/d2e094c41cf2a4f2a46268630ec2cb2f to your computer and use it in GitHub Desktop.
A reordering algorithm
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