This commit is contained in:
		
							
								
								
									
										168
									
								
								src/dllist.gleam
									
									
									
									
									
								
							
							
						
						
									
										168
									
								
								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),
 | 
			
		||||
          ),
 | 
			
		||||
        ),
 | 
			
		||||
      )
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user