Compare commits
2 Commits
f013d3320d
...
f9aa688f5d
| Author | SHA1 | Date | |
|---|---|---|---|
| f9aa688f5d | |||
| a5efb0ae8d |
@@ -17,3 +17,4 @@ gleam_stdlib = ">= 0.44.0 and < 2.0.0"
|
||||
|
||||
[dev-dependencies]
|
||||
gleeunit = ">= 1.0.0 and < 2.0.0"
|
||||
startest = ">= 0.7.0 and < 1.0.0"
|
||||
|
||||
@@ -2,10 +2,31 @@
|
||||
# You typically do not need to edit this file
|
||||
|
||||
packages = [
|
||||
{ name = "argv", version = "1.0.2", build_tools = ["gleam"], requirements = [], otp_app = "argv", source = "hex", outer_checksum = "BA1FF0929525DEBA1CE67256E5ADF77A7CDDFE729E3E3F57A5BDCAA031DED09D" },
|
||||
{ name = "bigben", version = "1.0.1", build_tools = ["gleam"], requirements = ["birl", "gleam_erlang", "gleam_otp", "gleam_stdlib"], otp_app = "bigben", source = "hex", outer_checksum = "190E489610A80D76C48BACC75EB8314BD184FF0220AB0F251ABE760B993B91BB" },
|
||||
{ name = "birl", version = "1.8.0", build_tools = ["gleam"], requirements = ["gleam_regexp", "gleam_stdlib", "ranger"], otp_app = "birl", source = "hex", outer_checksum = "2AC7BA26F998E3DFADDB657148BD5DDFE966958AD4D6D6957DD0D22E5B56C400" },
|
||||
{ name = "exception", version = "2.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "exception", source = "hex", outer_checksum = "329D269D5C2A314F7364BD2711372B6F2C58FA6F39981572E5CA68624D291F8C" },
|
||||
{ name = "filepath", version = "1.1.2", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "filepath", source = "hex", outer_checksum = "B06A9AF0BF10E51401D64B98E4B627F1D2E48C154967DA7AF4D0914780A6D40A" },
|
||||
{ name = "gleam_community_ansi", version = "1.4.3", build_tools = ["gleam"], requirements = ["gleam_community_colour", "gleam_regexp", "gleam_stdlib"], otp_app = "gleam_community_ansi", source = "hex", outer_checksum = "8A62AE9CC6EA65BEA630D95016D6C07E4F9973565FA3D0DE68DC4200D8E0DD27" },
|
||||
{ name = "gleam_community_colour", version = "2.0.2", build_tools = ["gleam"], requirements = ["gleam_json", "gleam_stdlib"], otp_app = "gleam_community_colour", source = "hex", outer_checksum = "E34DD2C896AC3792151EDA939DA435FF3B69922F33415ED3C4406C932FBE9634" },
|
||||
{ name = "gleam_erlang", version = "1.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_erlang", source = "hex", outer_checksum = "1124AD3AA21143E5AF0FC5CF3D9529F6DB8CA03E43A55711B60B6B7B3874375C" },
|
||||
{ name = "gleam_javascript", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_javascript", source = "hex", outer_checksum = "EF6C77A506F026C6FB37941889477CD5E4234FCD4337FF0E9384E297CB8F97EB" },
|
||||
{ name = "gleam_json", version = "3.0.2", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_json", source = "hex", outer_checksum = "874FA3C3BB6E22DD2BB111966BD40B3759E9094E05257899A7C08F5DE77EC049" },
|
||||
{ name = "gleam_otp", version = "1.2.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_stdlib"], otp_app = "gleam_otp", source = "hex", outer_checksum = "BA6A294E295E428EC1562DC1C11EA7530DCB981E8359134BEABC8493B7B2258E" },
|
||||
{ name = "gleam_regexp", version = "1.1.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_regexp", source = "hex", outer_checksum = "9C215C6CA84A5B35BB934A9B61A9A306EC743153BE2B0425A0D032E477B062A9" },
|
||||
{ name = "gleam_stdlib", version = "0.65.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "7C69C71D8C493AE11A5184828A77110EB05A7786EBF8B25B36A72F879C3EE107" },
|
||||
{ name = "gleam_time", version = "1.4.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_time", source = "hex", outer_checksum = "DCDDC040CE97DA3D2A925CDBBA08D8A78681139745754A83998641C8A3F6587E" },
|
||||
{ name = "gleam_yielder", version = "1.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_yielder", source = "hex", outer_checksum = "8E4E4ECFA7982859F430C57F549200C7749823C106759F4A19A78AEA6687717A" },
|
||||
{ name = "gleeunit", version = "1.6.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "FDC68A8C492B1E9B429249062CD9BAC9B5538C6FBF584817205D0998C42E1DAC" },
|
||||
{ name = "glint", version = "1.2.1", build_tools = ["gleam"], requirements = ["gleam_community_ansi", "gleam_community_colour", "gleam_stdlib", "snag"], otp_app = "glint", source = "hex", outer_checksum = "2214C7CEFDE457CEE62140C3D4899B964E05236DA74E4243DFADF4AF29C382BB" },
|
||||
{ name = "ranger", version = "1.4.0", build_tools = ["gleam"], requirements = ["gleam_stdlib", "gleam_yielder"], otp_app = "ranger", source = "hex", outer_checksum = "C8988E8F8CDBD3E7F4D8F2E663EF76490390899C2B2885A6432E942495B3E854" },
|
||||
{ name = "simplifile", version = "2.3.0", build_tools = ["gleam"], requirements = ["filepath", "gleam_stdlib"], otp_app = "simplifile", source = "hex", outer_checksum = "0A868DAC6063D9E983477981839810DC2E553285AB4588B87E3E9C96A7FB4CB4" },
|
||||
{ name = "snag", version = "1.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "snag", source = "hex", outer_checksum = "7E9F06390040EB5FAB392CE642771484136F2EC103A92AE11BA898C8167E6E17" },
|
||||
{ name = "startest", version = "0.7.0", build_tools = ["gleam"], requirements = ["argv", "bigben", "birl", "exception", "gleam_community_ansi", "gleam_erlang", "gleam_javascript", "gleam_regexp", "gleam_stdlib", "glint", "simplifile", "tom"], otp_app = "startest", source = "hex", outer_checksum = "71B9CB82C4B8779A4BD54C7151DF7D0B0F778D0DDE805B782B44EFA7BA8F50DA" },
|
||||
{ name = "tom", version = "2.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib", "gleam_time"], otp_app = "tom", source = "hex", outer_checksum = "74D0C5A3761F7A7D06994755D4D5AD854122EF8E9F9F76A3E7547606D8C77091" },
|
||||
]
|
||||
|
||||
[requirements]
|
||||
gleam_stdlib = { version = ">= 0.44.0 and < 2.0.0" }
|
||||
gleeunit = { version = ">= 1.0.0 and < 2.0.0" }
|
||||
startest = { version = ">= 0.7.0 and < 1.0.0" }
|
||||
|
||||
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),
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,21 @@
|
||||
import gleeunit
|
||||
import dllist
|
||||
import startest
|
||||
|
||||
pub fn main() -> Nil {
|
||||
gleeunit.main()
|
||||
startest.run(startest.default_config())
|
||||
}
|
||||
|
||||
// gleeunit test functions end in `_test`
|
||||
pub fn hello_world_test() {
|
||||
let name = "Joe"
|
||||
let greeting = "Hello, " <> name <> "!"
|
||||
pub fn is_empty_tests() {
|
||||
startest.describe("is_emtpy", [
|
||||
startest.it("terminated list", fn() {
|
||||
assert dllist.is_empty(dllist.new())
|
||||
|
||||
assert greeting == "Hello, Joe!"
|
||||
assert !dllist.is_empty(dllist.new() |> dllist.insert(1))
|
||||
}),
|
||||
startest.it("cyclic list", fn() {
|
||||
assert dllist.is_empty(dllist.new_cyclic())
|
||||
|
||||
assert !dllist.is_empty(dllist.new_cyclic() |> dllist.insert(1))
|
||||
}),
|
||||
])
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user