trackler 2.2.1.153 → 2.2.1.154
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/trackler/version.rb +1 -1
- data/problem-specifications/exercises/grade-school/canonical-data.json +68 -0
- data/problem-specifications/exercises/luhn/canonical-data.json +9 -1
- data/problem-specifications/exercises/say/description.md +1 -1
- data/problem-specifications/exercises/word-search/canonical-data.json +2 -3
- data/tracks/csharp/exercises/go-counting/Example.cs +49 -42
- data/tracks/csharp/exercises/go-counting/GoCounting.cs +3 -3
- data/tracks/csharp/exercises/go-counting/GoCountingTest.cs +137 -88
- data/tracks/csharp/exercises/palindrome-products/Example.cs +25 -34
- data/tracks/csharp/exercises/palindrome-products/PalindromeProducts.cs +3 -29
- data/tracks/csharp/exercises/palindrome-products/PalindromeProductsTest.cs +103 -0
- data/tracks/csharp/exercises/word-search/Example.cs +24 -16
- data/tracks/csharp/exercises/word-search/WordSearch.cs +2 -2
- data/tracks/csharp/exercises/word-search/WordSearchTest.cs +539 -66
- data/tracks/csharp/generators/Exercises/GoCounting.cs +95 -0
- data/tracks/csharp/generators/Exercises/PalindromeProducts.cs +47 -0
- data/tracks/csharp/generators/Exercises/WordSearch.cs +84 -0
- data/tracks/csharp/generators/Output/ValueFormatter.cs +6 -0
- data/tracks/delphi/exercises/grade-school/uGradeSchoolTest.pas +4 -4
- data/tracks/ecmascript/.travis.yml +3 -1
- data/tracks/ecmascript/exercises/linked-list/linked-list.spec.js +16 -0
- data/tracks/elm/config.json +9 -1
- data/tracks/elm/exercises/bracket-push/BracketPush.elm +6 -0
- data/tracks/elm/exercises/bracket-push/BracketPush.example.elm +50 -0
- data/tracks/elm/exercises/bracket-push/README.md +40 -0
- data/tracks/elm/exercises/bracket-push/elm-package.json +14 -0
- data/tracks/elm/exercises/bracket-push/tests/Tests.elm +71 -0
- data/tracks/elm/exercises/bracket-push/tests/elm-package.json +16 -0
- data/tracks/go/config.json +14 -3
- data/tracks/go/exercises/linked-list/README.md +59 -0
- data/tracks/go/exercises/linked-list/cases_test.go +189 -0
- data/tracks/go/exercises/linked-list/example.go +212 -0
- data/tracks/go/exercises/linked-list/linked_list_test.go +106 -0
- data/tracks/java/exercises/go-counting/.meta/src/reference/java/GoCounting.java +6 -12
- data/tracks/java/exercises/go-counting/src/test/java/GoCountingTest.java +12 -12
- data/tracks/java/exercises/kindergarten-garden/src/main/java/KindergartenGarden.java +0 -4
- data/tracks/python/exercises/hamming/README.md +4 -3
- data/tracks/rust/exercises/beer-song/src/lib.rs +7 -7
- data/tracks/rust/exercises/bob/src/lib.rs +3 -3
- data/tracks/rust/exercises/difference-of-squares/src/lib.rs +14 -14
- data/tracks/rust/exercises/leap/src/lib.rs +3 -3
- data/tracks/rust/exercises/perfect-numbers/src/lib.rs +10 -10
- data/tracks/rust/exercises/proverb/src/lib.rs +3 -3
- data/tracks/rust/exercises/pythagorean-triplet/src/lib.rs +3 -3
- data/tracks/rust/exercises/raindrops/src/lib.rs +3 -3
- data/tracks/rust/exercises/sum-of-multiples/src/lib.rs +3 -3
- metadata +17 -3
- data/tracks/csharp/exercises/palindrome-products/PalindromeTest.cs +0 -69
@@ -0,0 +1,71 @@
|
|
1
|
+
module Tests exposing (..)
|
2
|
+
|
3
|
+
import BracketPush exposing (isPaired)
|
4
|
+
import Expect
|
5
|
+
import String
|
6
|
+
import Test exposing (..)
|
7
|
+
|
8
|
+
|
9
|
+
tests : Test
|
10
|
+
tests =
|
11
|
+
describe "BracketPush"
|
12
|
+
[ test "paired square brackets" <|
|
13
|
+
\_ ->
|
14
|
+
Expect.equal True (isPaired "[]")
|
15
|
+
, skip <|
|
16
|
+
test "empty string" <|
|
17
|
+
\_ ->
|
18
|
+
Expect.equal True (isPaired "")
|
19
|
+
, skip <|
|
20
|
+
test "unpaired brackets" <|
|
21
|
+
\_ ->
|
22
|
+
Expect.equal False (isPaired "[[")
|
23
|
+
, skip <|
|
24
|
+
test "wrong ordered brackets" <|
|
25
|
+
\_ ->
|
26
|
+
Expect.equal False (isPaired "}{")
|
27
|
+
, skip <|
|
28
|
+
test "wrong closing bracket" <|
|
29
|
+
\_ ->
|
30
|
+
Expect.equal False (isPaired "{]")
|
31
|
+
, skip <|
|
32
|
+
test "paired with whitespace" <|
|
33
|
+
\_ ->
|
34
|
+
Expect.equal True (isPaired "{ }")
|
35
|
+
, skip <|
|
36
|
+
test "partially paired brackets" <|
|
37
|
+
\_ ->
|
38
|
+
Expect.equal False (isPaired "{[])")
|
39
|
+
, skip <|
|
40
|
+
test "simple nested brackets" <|
|
41
|
+
\_ ->
|
42
|
+
Expect.equal True (isPaired "{[]}")
|
43
|
+
, skip <|
|
44
|
+
test "seceral paired brackets" <|
|
45
|
+
\_ ->
|
46
|
+
Expect.equal True (isPaired "{}[]")
|
47
|
+
, skip <|
|
48
|
+
test "paired and nested brackets" <|
|
49
|
+
\_ ->
|
50
|
+
Expect.equal True (isPaired "([{}({}[])])")
|
51
|
+
, skip <|
|
52
|
+
test "unopened closing brackets" <|
|
53
|
+
\_ ->
|
54
|
+
Expect.equal False (isPaired "{[)][]}")
|
55
|
+
, skip <|
|
56
|
+
test "unpaired and nested brackets" <|
|
57
|
+
\_ ->
|
58
|
+
Expect.equal False (isPaired "([{])")
|
59
|
+
, skip <|
|
60
|
+
test "paired and wrong nested brackets" <|
|
61
|
+
\_ ->
|
62
|
+
Expect.equal False (isPaired "[({]})")
|
63
|
+
, skip <|
|
64
|
+
test "math expression" <|
|
65
|
+
\_ ->
|
66
|
+
Expect.equal True (isPaired "(((185 + 223.85) * 15) - 543)/2")
|
67
|
+
, skip <|
|
68
|
+
test "complex latex expression" <|
|
69
|
+
\_ ->
|
70
|
+
Expect.equal True (isPaired "\\left(\\begin{array}{cc} \\frac{1}{3} & x\\\\ \\mathrm{e}^{x} &... x^2 \\end{array}\\right)")
|
71
|
+
]
|
@@ -0,0 +1,16 @@
|
|
1
|
+
{
|
2
|
+
"version": "3.0.0",
|
3
|
+
"summary": "Exercism problems in Elm.",
|
4
|
+
"repository": "https://github.com/exercism/elm.git",
|
5
|
+
"license": "BSD3",
|
6
|
+
"source-directories": [
|
7
|
+
".",
|
8
|
+
".."
|
9
|
+
],
|
10
|
+
"exposed-modules": [],
|
11
|
+
"dependencies": {
|
12
|
+
"elm-lang/core": "5.0.0 <= v < 6.0.0",
|
13
|
+
"elm-community/elm-test": "4.0.0 <= v < 5.0.0"
|
14
|
+
},
|
15
|
+
"elm-version": "0.18.0 <= v < 0.19.0"
|
16
|
+
}
|
data/tracks/go/config.json
CHANGED
@@ -149,7 +149,7 @@
|
|
149
149
|
"unlocked_by": null,
|
150
150
|
"uuid": "8b29da0e-8ead-4e72-a12a-d448c8434767"
|
151
151
|
},
|
152
|
-
|
152
|
+
{
|
153
153
|
"core": true,
|
154
154
|
"difficulty": 2,
|
155
155
|
"slug": "grains",
|
@@ -908,6 +908,18 @@
|
|
908
908
|
"unlocked_by": "error-handling",
|
909
909
|
"uuid": "408f235e-f1ce-11e7-8c3f-9a214cf093ae"
|
910
910
|
},
|
911
|
+
{
|
912
|
+
"core": false,
|
913
|
+
"difficulty": 4,
|
914
|
+
"slug": "linked-list",
|
915
|
+
"topics": [
|
916
|
+
"pointer",
|
917
|
+
"data_structure"
|
918
|
+
],
|
919
|
+
"unlocked_by": "tree-building",
|
920
|
+
"uuid": "4368df53-39fb-4f36-97c2-39c399cd6d25"
|
921
|
+
},
|
922
|
+
|
911
923
|
{
|
912
924
|
"core": false,
|
913
925
|
"difficulty": 5,
|
@@ -1072,7 +1084,7 @@
|
|
1072
1084
|
"unlocked_by": "twelve-days",
|
1073
1085
|
"uuid": "a7469032-c4d0-4e15-aa0c-4e9f6588b4c8"
|
1074
1086
|
},
|
1075
|
-
{
|
1087
|
+
{
|
1076
1088
|
"core": false,
|
1077
1089
|
"difficulty": 4,
|
1078
1090
|
"slug": "yacht",
|
@@ -1340,7 +1352,6 @@
|
|
1340
1352
|
}
|
1341
1353
|
],
|
1342
1354
|
"foregone": [
|
1343
|
-
"linked-list"
|
1344
1355
|
],
|
1345
1356
|
"ignore_pattern": "example(?!.*test)",
|
1346
1357
|
"language": "Go"
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# Linked List
|
2
|
+
Implement a doubly linked list.
|
3
|
+
|
4
|
+
Like an array, a linked list is a simple linear data structure. Several
|
5
|
+
common data types can be implemented using linked lists, like queues,
|
6
|
+
stacks, and associative arrays.
|
7
|
+
|
8
|
+
A linked list is a collection of data elements called *nodes*. In a
|
9
|
+
*singly linked list* each node holds a value and a link to the next node.
|
10
|
+
In a *doubly linked list* each node also holds a link to the previous
|
11
|
+
node.
|
12
|
+
|
13
|
+
You will write an implementation of a doubly linked list. Implement a
|
14
|
+
`Node` to hold a value and pointers to the next and previous nodes. Then
|
15
|
+
implement a `List` which holds references to the first and last node and
|
16
|
+
offers functions for adding and removing items.
|
17
|
+
|
18
|
+
Your `Node` should have the following fields and functions:
|
19
|
+
|
20
|
+
* `Val`: the node's value (we will use `interface{}`).
|
21
|
+
* `Next()`: pointer to the next node.
|
22
|
+
* `Prev()`: pointer to the previous node.
|
23
|
+
* `First()`: pointer to the first node (head).
|
24
|
+
* `Last()`: pointer to the last node (tail).
|
25
|
+
|
26
|
+
Your `List` should have the following fields and functions:
|
27
|
+
|
28
|
+
* `First()`: pointer to the first node (head).
|
29
|
+
* `Last()`: pointer to the last node (tail).
|
30
|
+
* `PushBack(v interface{})`: insert value at back.
|
31
|
+
* `PopBack() (interface{}, error)`: remove value at back.
|
32
|
+
* `PushFront(v interface{}) `: remove value at front.
|
33
|
+
* `PopFront() (interface{}, error)`: insert value at front.
|
34
|
+
* `Reverse()`: reverse the linked list.
|
35
|
+
|
36
|
+
Instead of not covering error conditions, like calling `PopBack` or `PopFront` on an empty list,
|
37
|
+
we will follow Go's idiomatic style and implement the error checks as well.
|
38
|
+
|
39
|
+
If you want to know more about linked lists, check [Wikipedia](https://en.wikipedia.org/wiki/Linked_list).
|
40
|
+
|
41
|
+
## Running the tests
|
42
|
+
To run the tests run the command `go test` from within the exercise directory.
|
43
|
+
|
44
|
+
If the test suite contains benchmarks, you can run these with the `-bench`
|
45
|
+
flag:
|
46
|
+
|
47
|
+
go test -bench .
|
48
|
+
|
49
|
+
Keep in mind that each reviewer will run benchmarks on a different machine, with
|
50
|
+
different specs, so the results from these benchmark tests may vary.
|
51
|
+
|
52
|
+
## Further information
|
53
|
+
If you are not familar with linked list, try [this tutorial](https://visualgo.net/en/list).
|
54
|
+
|
55
|
+
## Source
|
56
|
+
Classic CS data structure.
|
57
|
+
|
58
|
+
## Submitting Incomplete Solutions
|
59
|
+
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
@@ -0,0 +1,189 @@
|
|
1
|
+
package linkedlist
|
2
|
+
|
3
|
+
import "testing"
|
4
|
+
|
5
|
+
var newListTestCases = []struct {
|
6
|
+
name string
|
7
|
+
in []interface{}
|
8
|
+
expected []interface{}
|
9
|
+
}{
|
10
|
+
{
|
11
|
+
name: "from 5 elements",
|
12
|
+
in: []interface{}{1, 2, 3, 4, 5},
|
13
|
+
expected: []interface{}{1, 2, 3, 4, 5},
|
14
|
+
},
|
15
|
+
{
|
16
|
+
name: "from 2 elements",
|
17
|
+
in: []interface{}{1, 2},
|
18
|
+
expected: []interface{}{1, 2},
|
19
|
+
},
|
20
|
+
{
|
21
|
+
name: "from no element",
|
22
|
+
in: []interface{}{},
|
23
|
+
expected: []interface{}{},
|
24
|
+
},
|
25
|
+
{
|
26
|
+
name: "from 1 element",
|
27
|
+
in: []interface{}{999},
|
28
|
+
expected: []interface{}{999},
|
29
|
+
},
|
30
|
+
}
|
31
|
+
|
32
|
+
var reverseTestCases = []struct {
|
33
|
+
name string
|
34
|
+
in []interface{}
|
35
|
+
expected []interface{}
|
36
|
+
}{
|
37
|
+
{
|
38
|
+
name: "from 5 elements",
|
39
|
+
in: []interface{}{1, 2, 3, 4, 5},
|
40
|
+
expected: []interface{}{5, 4, 3, 2, 1},
|
41
|
+
},
|
42
|
+
{
|
43
|
+
name: "from 2 elements",
|
44
|
+
in: []interface{}{1, 2},
|
45
|
+
expected: []interface{}{2, 1},
|
46
|
+
},
|
47
|
+
{
|
48
|
+
name: "from no element",
|
49
|
+
in: []interface{}{},
|
50
|
+
expected: []interface{}{},
|
51
|
+
},
|
52
|
+
{
|
53
|
+
name: "from 1 element",
|
54
|
+
in: []interface{}{999},
|
55
|
+
expected: []interface{}{999},
|
56
|
+
},
|
57
|
+
}
|
58
|
+
|
59
|
+
var pushPopTestCases = []struct {
|
60
|
+
name string
|
61
|
+
in []interface{}
|
62
|
+
actions []checkedAction
|
63
|
+
expected []interface{}
|
64
|
+
}{
|
65
|
+
{
|
66
|
+
name: "PushFront only",
|
67
|
+
in: []interface{}{},
|
68
|
+
actions: []checkedAction{
|
69
|
+
pushFront(4),
|
70
|
+
pushFront(3),
|
71
|
+
pushFront(2),
|
72
|
+
pushFront(1),
|
73
|
+
},
|
74
|
+
expected: []interface{}{1, 2, 3, 4},
|
75
|
+
},
|
76
|
+
{
|
77
|
+
name: "PushBack only",
|
78
|
+
in: []interface{}{},
|
79
|
+
actions: []checkedAction{
|
80
|
+
pushBack(1),
|
81
|
+
pushBack(2),
|
82
|
+
pushBack(3),
|
83
|
+
pushBack(4),
|
84
|
+
},
|
85
|
+
expected: []interface{}{1, 2, 3, 4},
|
86
|
+
},
|
87
|
+
{
|
88
|
+
name: "PopFront only, pop some elements",
|
89
|
+
in: []interface{}{1, 2, 3, 4},
|
90
|
+
actions: []checkedAction{
|
91
|
+
popFront(1, nil),
|
92
|
+
popFront(2, nil),
|
93
|
+
},
|
94
|
+
expected: []interface{}{3, 4},
|
95
|
+
},
|
96
|
+
{
|
97
|
+
name: "PopFront only, pop till empty",
|
98
|
+
in: []interface{}{1, 2, 3, 4},
|
99
|
+
actions: []checkedAction{
|
100
|
+
popFront(1, nil),
|
101
|
+
popFront(2, nil),
|
102
|
+
popFront(3, nil),
|
103
|
+
popFront(4, nil),
|
104
|
+
popFront(0, ErrEmptyList),
|
105
|
+
},
|
106
|
+
expected: []interface{}{},
|
107
|
+
},
|
108
|
+
{
|
109
|
+
name: "PopBack only, pop some elements",
|
110
|
+
in: []interface{}{1, 2, 3, 4},
|
111
|
+
actions: []checkedAction{
|
112
|
+
popBack(4, nil),
|
113
|
+
popBack(3, nil),
|
114
|
+
},
|
115
|
+
expected: []interface{}{1, 2},
|
116
|
+
},
|
117
|
+
{
|
118
|
+
name: "PopBack only, pop till empty",
|
119
|
+
in: []interface{}{1, 2, 3, 4},
|
120
|
+
actions: []checkedAction{
|
121
|
+
popBack(4, nil),
|
122
|
+
popBack(3, nil),
|
123
|
+
popBack(2, nil),
|
124
|
+
popBack(1, nil),
|
125
|
+
popBack(0, ErrEmptyList),
|
126
|
+
},
|
127
|
+
expected: []interface{}{},
|
128
|
+
},
|
129
|
+
{
|
130
|
+
name: "mixed actions",
|
131
|
+
in: []interface{}{2, 3},
|
132
|
+
actions: []checkedAction{
|
133
|
+
pushFront(1),
|
134
|
+
pushBack(4),
|
135
|
+
popFront(1, nil),
|
136
|
+
popFront(2, nil),
|
137
|
+
popBack(4, nil),
|
138
|
+
popBack(3, nil),
|
139
|
+
popBack(0, ErrEmptyList),
|
140
|
+
popFront(0, ErrEmptyList),
|
141
|
+
pushFront(8),
|
142
|
+
pushBack(7),
|
143
|
+
pushFront(9),
|
144
|
+
pushBack(6),
|
145
|
+
},
|
146
|
+
expected: []interface{}{9, 8, 7, 6},
|
147
|
+
},
|
148
|
+
}
|
149
|
+
|
150
|
+
// checkedAction calls a function of the linked list and (possibly) checks the result
|
151
|
+
type checkedAction func(*testing.T, *List)
|
152
|
+
|
153
|
+
func pushFront(arg interface{}) checkedAction {
|
154
|
+
return func(t *testing.T, ll *List) {
|
155
|
+
ll.PushFront(arg)
|
156
|
+
}
|
157
|
+
}
|
158
|
+
|
159
|
+
func pushBack(arg interface{}) checkedAction {
|
160
|
+
return func(t *testing.T, ll *List) {
|
161
|
+
ll.PushBack(arg)
|
162
|
+
}
|
163
|
+
}
|
164
|
+
|
165
|
+
func popFront(expected interface{}, expectedErr error) checkedAction {
|
166
|
+
return func(t *testing.T, ll *List) {
|
167
|
+
v, err := ll.PopFront()
|
168
|
+
if err != expectedErr {
|
169
|
+
t.Errorf("PopFront() returned wrong, expected no error, got= %v", err)
|
170
|
+
}
|
171
|
+
|
172
|
+
if v != expected {
|
173
|
+
t.Errorf("PopFront() returned wrong, expected= %v, got= %v", expected, v)
|
174
|
+
}
|
175
|
+
}
|
176
|
+
}
|
177
|
+
|
178
|
+
func popBack(expected interface{}, expectedErr error) checkedAction {
|
179
|
+
return func(t *testing.T, ll *List) {
|
180
|
+
v, err := ll.PopBack()
|
181
|
+
if err != expectedErr {
|
182
|
+
t.Errorf("PopBack() returned wrong, expected no error, got= %v", err)
|
183
|
+
}
|
184
|
+
|
185
|
+
if v != expected {
|
186
|
+
t.Errorf("PopBack() returned wrong, expected= %v, got= %v", expected, v)
|
187
|
+
}
|
188
|
+
}
|
189
|
+
}
|
@@ -0,0 +1,212 @@
|
|
1
|
+
package linkedlist
|
2
|
+
|
3
|
+
import (
|
4
|
+
"errors"
|
5
|
+
)
|
6
|
+
|
7
|
+
// Node is a node in a linked list.
|
8
|
+
type Node struct {
|
9
|
+
Val interface{}
|
10
|
+
next *Node
|
11
|
+
prev *Node
|
12
|
+
}
|
13
|
+
|
14
|
+
// NewNode constructs a new Node with the given value & no next/prev links.
|
15
|
+
func NewNode(v interface{}) *Node {
|
16
|
+
return &Node{
|
17
|
+
Val: v,
|
18
|
+
next: nil,
|
19
|
+
prev: nil,
|
20
|
+
}
|
21
|
+
}
|
22
|
+
|
23
|
+
// Next returns a pointer to the next node in the linked list.
|
24
|
+
func (n *Node) Next() *Node {
|
25
|
+
return n.next
|
26
|
+
}
|
27
|
+
|
28
|
+
// Prev returns a pointer to the previous node in the linked list.
|
29
|
+
func (n *Node) Prev() *Node {
|
30
|
+
return n.prev
|
31
|
+
}
|
32
|
+
|
33
|
+
// First returns a pointer to the first node in the linked list (head).
|
34
|
+
func (n *Node) First() *Node {
|
35
|
+
cur := n
|
36
|
+
for ; cur.prev != nil; cur = cur.prev {
|
37
|
+
}
|
38
|
+
|
39
|
+
return cur
|
40
|
+
}
|
41
|
+
|
42
|
+
// Last returns a pointer to the last node in the linked list (tail).
|
43
|
+
func (n *Node) Last() *Node {
|
44
|
+
cur := n
|
45
|
+
for ; cur.next != nil; cur = cur.next {
|
46
|
+
}
|
47
|
+
|
48
|
+
return cur
|
49
|
+
}
|
50
|
+
|
51
|
+
// List is a doubly-linked list with Head and Tail.
|
52
|
+
type List struct {
|
53
|
+
head *Node
|
54
|
+
tail *Node
|
55
|
+
}
|
56
|
+
|
57
|
+
// NewList constructs a doubly linked list from a sequence of integers.
|
58
|
+
func NewList(vs ...interface{}) *List {
|
59
|
+
ll := &List{
|
60
|
+
head: nil,
|
61
|
+
tail: nil,
|
62
|
+
}
|
63
|
+
|
64
|
+
if len(vs) < 1 {
|
65
|
+
return ll
|
66
|
+
}
|
67
|
+
|
68
|
+
ll.head = NewNode(vs[0])
|
69
|
+
ll.tail = ll.head
|
70
|
+
|
71
|
+
if len(vs) == 1 {
|
72
|
+
return ll
|
73
|
+
}
|
74
|
+
|
75
|
+
cur := ll.head
|
76
|
+
for i := 1; i < len(vs); i++ {
|
77
|
+
cur.next = NewNode(vs[i])
|
78
|
+
cur.next.prev = cur
|
79
|
+
cur = cur.next
|
80
|
+
}
|
81
|
+
|
82
|
+
ll.tail = cur
|
83
|
+
|
84
|
+
return ll
|
85
|
+
}
|
86
|
+
|
87
|
+
// First returns a pointer to the first node in the linked list (head).
|
88
|
+
func (ll *List) First() *Node {
|
89
|
+
return ll.head
|
90
|
+
}
|
91
|
+
|
92
|
+
// Last returns a pointer to the last node in the linked list (tail).
|
93
|
+
func (ll *List) Last() *Node {
|
94
|
+
return ll.tail
|
95
|
+
}
|
96
|
+
|
97
|
+
// Reverse reverses the given linked list in-place.
|
98
|
+
func (ll *List) Reverse() {
|
99
|
+
if ll.head == nil || ll.head.next == nil {
|
100
|
+
return
|
101
|
+
}
|
102
|
+
|
103
|
+
// construct singly-linked list from the back
|
104
|
+
dummy := NewNode(-1)
|
105
|
+
cur := dummy
|
106
|
+
n := ll.tail
|
107
|
+
for n != nil {
|
108
|
+
cur.next = n
|
109
|
+
|
110
|
+
cur = cur.next
|
111
|
+
n = n.prev
|
112
|
+
}
|
113
|
+
cur.next = nil // cur will be the new ll.Tail -> set .next = nil
|
114
|
+
|
115
|
+
// add prev -> doubly-linked list
|
116
|
+
prev := dummy.next
|
117
|
+
n = dummy.next.next
|
118
|
+
for n != nil {
|
119
|
+
n.prev = prev
|
120
|
+
|
121
|
+
n = n.next
|
122
|
+
prev = prev.next
|
123
|
+
}
|
124
|
+
|
125
|
+
// update Head & Tail
|
126
|
+
ll.head, ll.tail = ll.tail, ll.head
|
127
|
+
ll.head.prev = nil
|
128
|
+
}
|
129
|
+
|
130
|
+
// PushFront pushes a new value before Head.
|
131
|
+
func (ll *List) PushFront(v interface{}) {
|
132
|
+
n := NewNode(v)
|
133
|
+
|
134
|
+
switch {
|
135
|
+
default:
|
136
|
+
panic("bad PushFront implementation")
|
137
|
+
case ll.head == nil && ll.tail == nil: // empty list
|
138
|
+
ll.head = n
|
139
|
+
ll.tail = n
|
140
|
+
case ll.head != nil && ll.tail != nil: // non-empty list
|
141
|
+
n.next = ll.head
|
142
|
+
ll.head.prev = n
|
143
|
+
|
144
|
+
ll.head = n
|
145
|
+
}
|
146
|
+
}
|
147
|
+
|
148
|
+
// PushBack pushes a new value after Tail.
|
149
|
+
func (ll *List) PushBack(v interface{}) {
|
150
|
+
n := NewNode(v)
|
151
|
+
|
152
|
+
switch {
|
153
|
+
default:
|
154
|
+
panic("bad PushBack implementation")
|
155
|
+
case ll.head == nil && ll.tail == nil: // empty list
|
156
|
+
ll.head = n
|
157
|
+
ll.tail = n
|
158
|
+
case ll.head != nil && ll.tail != nil: // non-empty list
|
159
|
+
ll.tail.next = n
|
160
|
+
n.prev = ll.tail
|
161
|
+
|
162
|
+
ll.tail = n
|
163
|
+
}
|
164
|
+
}
|
165
|
+
|
166
|
+
var (
|
167
|
+
ErrEmptyList = errors.New("list is empty")
|
168
|
+
)
|
169
|
+
|
170
|
+
// PopFront posp the element at Head. It returns error if the linked list is empty.
|
171
|
+
func (ll *List) PopFront() (interface{}, error) {
|
172
|
+
switch {
|
173
|
+
default:
|
174
|
+
panic("bad PopFront implementation")
|
175
|
+
case ll.head == nil && ll.tail == nil: // empty list
|
176
|
+
return 0, ErrEmptyList
|
177
|
+
case ll.head != nil && ll.tail != nil && ll.head.next == nil: // 1 element
|
178
|
+
v := ll.head.Val
|
179
|
+
ll.head = nil
|
180
|
+
ll.tail = nil
|
181
|
+
|
182
|
+
return v, nil
|
183
|
+
case ll.head != nil && ll.tail != nil && ll.head.next != nil: // >1 element
|
184
|
+
v := ll.head.Val
|
185
|
+
ll.head.next.prev = nil
|
186
|
+
ll.head = ll.head.next
|
187
|
+
|
188
|
+
return v, nil
|
189
|
+
}
|
190
|
+
}
|
191
|
+
|
192
|
+
// PopBack pops the element at Tail. It returns error if the linked list is empty.
|
193
|
+
func (ll *List) PopBack() (interface{}, error) {
|
194
|
+
switch {
|
195
|
+
default:
|
196
|
+
panic("bad PopBack implementation")
|
197
|
+
case ll.head == nil && ll.tail == nil: // empty list
|
198
|
+
return 0, ErrEmptyList
|
199
|
+
case ll.head != nil && ll.tail != nil && ll.tail.prev == nil: // 1 element
|
200
|
+
v := ll.tail.Val
|
201
|
+
ll.head = nil
|
202
|
+
ll.tail = nil
|
203
|
+
|
204
|
+
return v, nil
|
205
|
+
case ll.head != nil && ll.tail != nil && ll.tail.prev != nil: // >1 element
|
206
|
+
v := ll.tail.Val
|
207
|
+
ll.tail.prev.next = nil
|
208
|
+
ll.tail = ll.tail.prev
|
209
|
+
|
210
|
+
return v, nil
|
211
|
+
}
|
212
|
+
}
|