Skip to content

Commit

Permalink
Exercise: simple-linked-list
Browse files Browse the repository at this point in the history
  • Loading branch information
loziniak committed Mar 2, 2022
2 parents d2730bb + 9821bd0 commit ccd2b53
Show file tree
Hide file tree
Showing 10 changed files with 284 additions and 4 deletions.
3 changes: 2 additions & 1 deletion _templates/practice-exercise/testlib.red
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,9 @@ context [
rejoin ["(ignored)"]
]

print [
print rejoin [
pad/with summary 40 #"."
"... "
result
]

Expand Down
8 changes: 6 additions & 2 deletions _tools/generate-practice-exercise.red
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,12 @@ write/lines/append rejoin [exercise-path %/.docs/instructions.md] instructions
; ===========================
print " TEST SUITE ..."

canonical-data: load-json read
rejoin [github-problem-spec %/canonical-data.json]
canonical-data: unless map? canonical-data: try [
load-json read
rejoin [github-problem-spec %/canonical-data.json]
] [
#( cases: [])
]

camel-to-kebab-case: function [
"Converts a string in camelCase to kebab-case"
Expand Down
17 changes: 16 additions & 1 deletion config.json
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@
"prerequisites": [
"basics"
],
"difficulty": 1
"difficulty": 2
},
{
"slug": "resistor-color",
Expand Down Expand Up @@ -342,6 +342,21 @@
],
"difficulty": 7
},
{
"slug": "simple-linked-list",
"name": "Simple Linked List",
"status": "beta",
"uuid": "55399872-3758-4424-80a1-36b1f80ad7b2",
"practices": [
"blocks",
"loops",
"functions"
],
"prerequisites": [
"loops"
],
"difficulty": 7
},
{
"slug": "circular-buffer",
"name": "Circular Buffer",
Expand Down
22 changes: 22 additions & 0 deletions exercises/practice/simple-linked-list/.docs/instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Instructions

Write a simple linked list implementation that uses Elements and a List.

The linked list is a fundamental data structure in computer science,
often used in the implementation of other data structures. They're
pervasive in functional programming languages, such as Clojure, Erlang,
or Haskell, but far less common in imperative languages such as Ruby or
Python.

The simplest kind of linked list is a singly linked list. Each element in the
list contains data and a "next" field pointing to the next element in the list
of elements.

This variant of linked lists is often used to represent sequences or
push-down stacks (also called a LIFO stack; Last In, First Out).

As a first take, lets create a singly linked list to contain the range (1..10),
and provide functions to reverse a linked list and convert to and from arrays.

When implementing this in a language with built-in linked lists,
implement your own abstract data type.
18 changes: 18 additions & 0 deletions exercises/practice/simple-linked-list/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"blurb": "Write a simple linked list implementation that uses Elements and a List.",
"authors": [
"loziniak"
],
"contributors": [],
"files": {
"solution": [
"simple-linked-list.red"
],
"test": [
"simple-linked-list-test.red"
],
"example": [
".meta/example.red"
]
}
}
56 changes: 56 additions & 0 deletions exercises/practice/simple-linked-list/.meta/example.red
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
Red [
description: {"Simple Linked List" exercise solution for exercism platform}
author: "loziniak"
]


to-array: function [
list [block! none!]
return: [vector!]
] [
array: make vector! []
while [not none? list] [
append array list/1
list: list/2
]
array
]

from-array: function [
array [vector!]
return: [block! none!]
] [
list: none
loop element: length? array [
list: reduce [array/(element) list]
element: element - 1
]
list
]

reverse-list: function [
list [block! none!]
return: [block! none!]
] [
reversed: none
while [not none? list] [
reversed: reduce [list/1 reversed]
list: list/2
]
reversed
]


from-array-and-back: function [
array [block!]
return: [block!]
] [
to block! to-array from-array make vector! array
]

convert-reverse-convert-back: function [
array [block!]
return: [block!]
] [
to block! to-array reverse-list from-array make vector! array
]
13 changes: 13 additions & 0 deletions exercises/practice/simple-linked-list/.meta/tests.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[canonical-tests]

# Convert an array to linked list, and then from linked list back to array
"3b72d23a-4487-4632-8682-59684c875dd9" = true

# Convert from array, reverse the list, and covert to array
"70484949-cf28-4446-af05-e24f5ae8a265" = true

# Convert empty array
"02fb7cdd-ad7f-4d0b-88b7-a3e0ccfcb584" = true

# Convert and reverse empty array
"410ed9b3-d4cd-4969-bc5e-3909efed65d8" = true
54 changes: 54 additions & 0 deletions exercises/practice/simple-linked-list/simple-linked-list-test.red
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
Red [
description: {Tests for "Simple Linked List" Exercism exercise}
author: "loziniak"
]

#include %testlib.red

test-init/limit %simple-linked-list.red 1
; test-init/limit %.meta/example.red 1 ; test example solution

canonical-cases: [#(
description: {Convert an array to linked list, and then from linked list back to array}
input: #(
array: [3 6 1]
)
expected: [3 6 1]
function: "from-array-and-back"
uuid: "3b72d23a-4487-4632-8682-59684c875dd9"
) #(
description: {Convert from array, reverse the list, and covert to array}
input: #(
array: [3 6 1]
)
expected: [1 6 3]
function: "convert-reverse-convert-back"
uuid: "70484949-cf28-4446-af05-e24f5ae8a265"
) #(
description: {Convert empty array}
input: #(
array: []
)
expected: []
function: "from-array-and-back"
uuid: "02fb7cdd-ad7f-4d0b-88b7-a3e0ccfcb584"
) #(
description: {Convert and reverse empty array}
input: #(
array: []
)
expected: []
function: "convert-reverse-convert-back"
uuid: "410ed9b3-d4cd-4969-bc5e-3909efed65d8"
)]


foreach c-case canonical-cases [
case-code: reduce [
'expect c-case/expected compose [
(to word! c-case/function) (values-of c-case/input)
]
]

test c-case/description case-code
]
17 changes: 17 additions & 0 deletions exercises/practice/simple-linked-list/simple-linked-list.red
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
Red [
description: {"Simple Linked List" exercise solution for exercism platform}
author: "" ; you can write your name here, in quotes
]

from-array-and-back: function [
array
] [
cause-error 'user 'message ["You need to implement this function."]
]

convert-reverse-convert-back: function [
array
] [
cause-error 'user 'message ["You need to implement this function."]
]

80 changes: 80 additions & 0 deletions exercises/practice/simple-linked-list/testlib.red
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
Red [
description: {Unit testing library}
author: "loziniak"
]


context [
tested: 0
ignore-after: none
test-file: none

set 'test-init function [
file [file!]
/limit
ia [integer!]
] [
self/test-file: file
if limit [
self/ignore-after: ia
]
]

sandbox!: context [

expect: function [
expectation
code [block!]
] [
result: try [
catch code
]

if error? result [
either result/type = 'user [
result: make map! reduce ['error result/arg1]
] [
throw result
]
]

unless result = expectation [
throw rejoin [{FAILED. Expected: } expectation {, but got } result]
]

result
]
]

set 'test function [
summary [string!]
code [block!]
/extern
tested
] [
result: either any [
none? ignore-after
tested < ignore-after
] [
exercise: make sandbox! load test-file

code: bind code exercise

catch [
do code
"✓"
]
] [
rejoin ["(ignored)"]
]

print rejoin [
pad/with summary 40 #"."
"... "
result
]

tested: tested + 1
]

]

0 comments on commit ccd2b53

Please sign in to comment.