From f9aa688f5dadf506b22b575e0939e49307d7e204 Mon Sep 17 00:00:00 2001 From: Gareth Pendleton Date: Sun, 19 Oct 2025 22:51:33 +0100 Subject: [PATCH] fix: Reworked some api functions --- src/dllist.gleam | 168 ++++++++++++++++++++++++++++++----------------- 1 file changed, 108 insertions(+), 60 deletions(-) diff --git a/src/dllist.gleam b/src/dllist.gleam index 4af3a3d..3430225 100644 --- a/src/dllist.gleam +++ b/src/dllist.gleam @@ -11,7 +11,7 @@ pub opaque type Node(a) { pub type DLList(a) { DLList(counter: Int, current: Int, mem: dict.Dict(Int, Node(a))) - // CyclicList(counter: Int, current: Int, mem: dict.Dict(Int, Node(a))) + CyclicList(counter: Int, current: Int, mem: dict.Dict(Int, Node(a))) } pub fn main() { @@ -39,23 +39,35 @@ pub fn main() { l1 |> echo let l1t = take(l1, 5) l1t |> echo - let l2 = insert(l1, 2) + let l2 = insert(l1, 2) |> move_left l2 |> echo let l2t = take(l2, 5) l2t |> echo let l3 = insert(l2, 3) l3 |> echo - let l3t = take(l3, 7) - l3t |> echo - let l3t2 = take_rev(l3, 7) - l3t2 |> echo + to_list(l3) |> echo + // let l3t = take(l3, 7) + // l3t |> echo + // let l3t2 = take_rev(l3, 7) + // l3t2 |> echo } pub fn new() -> DLList(a) { DLList(1, 0, dict.new()) } +pub fn new_cyclic() -> DLList(a) { + CyclicList(1, 0, dict.new()) +} + +fn clear(list: DLList(a)) -> DLList(a) { + case list { + DLList(_, _, _) -> DLList(1, 0, dict.new()) + CyclicList(_, _, _) -> CyclicList(1, 0, dict.new()) + } +} + fn get_curr_node(list: DLList(a)) -> Result(Node(a), Nil) { dict.get(list.mem, list.current) } @@ -70,9 +82,13 @@ pub fn is_empty(list: DLList(a)) -> Bool { pub fn insert(list: DLList(a), val: a) -> DLList(a) { let ref = list.counter + let new_entry_ref = case list { + DLList(_, _, _) -> 0 + CyclicList(_, _, _) -> ref + } case is_empty(list) { True -> { - let node = Node(val, ref, ref) + let node = Node(val, new_entry_ref, new_entry_ref) DLList(ref + 1, ref, dict.insert(list.mem, ref, node)) } False -> { @@ -104,6 +120,17 @@ pub fn insert(list: DLList(a), val: a) -> DLList(a) { } } +fn update_record( + list: DLList(a), + current: Int, + mem: dict.Dict(Int, Node(a)), +) -> DLList(a) { + case list { + DLList(_, _, _) -> DLList(..list, current:, mem:) + CyclicList(_, _, _) -> CyclicList(..list, current:, mem:) + } +} + pub fn delete(list: DLList(a)) -> DLList(a) { let #(mem, curr_node) = remove_lookup(list, list.current) case curr_node { @@ -112,52 +139,50 @@ pub fn delete(list: DLList(a)) -> DLList(a) { let l = curr_node.left let r = curr_node.right case l, r { - 0, 0 -> new() - 0, n if n == list.current -> new() - n, 0 if n == list.current -> new() - n, m if n == list.current && m == list.current -> new() + 0, 0 -> clear(list) + 0, n if n == list.current -> clear(list) + n, 0 if n == list.current -> clear(list) + n, m if n == list.current && m == list.current -> clear(list) _, 0 -> { - DLList( - ..list, - current: l, - mem: update_dict_entry(mem, l, fn(n) { Node(..n, right: r) }), + update_record( + list, + l, + update_dict_entry(mem, l, fn(n) { Node(..n, right: r) }), ) } _, r if r == list.current -> { - DLList( - ..list, - current: l, - mem: update_dict_entry(mem, l, fn(n) { Node(..n, right: l) }), + update_record( + list, + l, + update_dict_entry(mem, l, fn(n) { Node(..n, right: l) }), ) } 0, _ -> { - DLList( - ..list, - current: r, - mem: update_dict_entry(mem, r, fn(n) { Node(..n, left: l) }), + update_record( + list, + r, + update_dict_entry(mem, r, fn(n) { Node(..n, left: l) }), ) } l, _ if l == list.current -> { - DLList( - ..list, - current: r, - mem: update_dict_entry(mem, r, fn(n) { Node(..n, left: r) }), + update_record( + list, + r, + update_dict_entry(mem, r, fn(n) { Node(..n, left: r) }), ) } l, r if l == r -> { - DLList( - ..list, - current: r, - mem: update_dict_entry(mem, r, fn(n) { - Node(..n, left: r, right: r) - }), + update_record( + list, + r, + update_dict_entry(mem, r, fn(n) { Node(..n, left: r, right: r) }), ) } _, _ -> { - DLList( - ..list, - current: r, - mem: update_dict_entry(mem, r, fn(n) { Node(..n, left: l) }) + update_record( + list, + r, + update_dict_entry(mem, r, fn(n) { Node(..n, left: l) }) |> update_dict_entry(l, fn(n) { Node(..n, right: r) }), ) } @@ -174,9 +199,10 @@ fn do_move_right(list: DLList(a)) -> Result(DLList(a), Nil) { case get_curr_node(list) { Error(_) -> Error(Nil) Ok(node) -> { - case node.right { - 0 -> Ok(list) - r -> Ok(DLList(..list, current: r)) + case node.right, list { + 0, _ -> Error(Nil) + r, DLList(_, _, _) -> Ok(DLList(..list, current: r)) + r, CyclicList(_, _, _) -> Ok(CyclicList(..list, current: r)) } } } @@ -191,9 +217,10 @@ fn do_move_left(list: DLList(a)) -> Result(DLList(a), Nil) { case get_curr_node(list) { Error(_) -> Error(Nil) Ok(node) -> { - case node.left { - 0 -> Ok(list) - l -> Ok(DLList(..list, current: l)) + case node.left, list { + 0, _ -> Error(Nil) + l, DLList(_, _, _) -> Ok(DLList(..list, current: l)) + l, CyclicList(_, _, _) -> Ok(CyclicList(..list, current: l)) } } } @@ -208,13 +235,19 @@ pub fn take(list: DLList(a), n_times: Int) -> List(a) { } fn take_loop(list: DLList(a), n_times: Int, acc: List(a)) -> List(a) { + list |> echo use <- bool.guard(when: is_empty(list), return: []) case n_times { 0 -> list.reverse(acc) n -> { case get(list) { Error(_) -> [] - Ok(item) -> take_rev_loop(move_right(list), n - 1, [item, ..acc]) + Ok(item) -> { + case move_right(list) { + r if r != list -> take_loop(r, n - 1, [item, ..acc]) + _ -> list.reverse([item, ..acc]) + } + } } } } @@ -231,32 +264,36 @@ fn take_rev_loop(list: DLList(a), n_times: Int, acc: List(a)) -> List(a) { n -> { case get(list) { Error(_) -> [] - Ok(item) -> take_rev_loop(move_left(list), n - 1, [item, ..acc]) + Ok(item) -> { + case move_left(list) { + l if l != list -> take_rev_loop(l, n - 1, [item, ..acc]) + _ -> list.reverse([item, ..acc]) + } + } } } } } pub fn to_list(list: DLList(a)) -> List(a) { - case is_empty(list) { - True -> [] - False -> { - case get(list) { - Error(_) -> [] - Ok(val) -> [val, ..to_list_loop(do_move_right(list), list.current)] - } - } + let list = case list { + DLList(_, _, _) -> DLList(..list, current: 1) + CyclicList(_, _, _) -> list } + to_list_loop(Ok(list), list.current, []) } -fn to_list_loop(list: Result(DLList(a), Nil), start_ref: Int) -> List(a) { +fn to_list_loop( + list: Result(DLList(a), Nil), + start_ref: Int, + acc: List(a), +) -> List(a) { case list { - Error(_) -> [] - Ok(DLList(_, current, _)) if current == start_ref -> [] + Error(_) -> list.reverse(acc) Ok(list) -> { case get(list) { Error(_) -> [] - Ok(val) -> [val, ..to_list_loop(do_move_right(list), start_ref)] + Ok(val) -> to_list_loop(do_move_right(list), start_ref, [val, ..acc]) } } } @@ -264,9 +301,9 @@ fn to_list_loop(list: Result(DLList(a), Nil), start_ref: Int) -> List(a) { pub fn update(list: DLList(a), value: a) -> Result(DLList(a), Nil) { use <- bool.guard(when: is_empty(list), return: Error(Nil)) - case get_curr_node(list) { - Error(_) -> Error(Nil) - Ok(curr_node) -> + case get_curr_node(list), list { + Error(_), _ -> Error(Nil) + Ok(curr_node), DLList(_, _, _) -> Ok( DLList( ..list, @@ -277,6 +314,17 @@ pub fn update(list: DLList(a), value: a) -> Result(DLList(a), Nil) { ), ), ) + Ok(curr_node), CyclicList(_, _, _) -> + Ok( + CyclicList( + ..list, + mem: dict.insert( + list.mem, + list.current, + Node(..curr_node, val: value), + ), + ), + ) } }