-
Notifications
You must be signed in to change notification settings - Fork 0
/
ordered_concatenations.sf
130 lines (96 loc) · 2.52 KB
/
ordered_concatenations.sf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#!/usr/bin/ruby
# Daniel "Trizen" Șuteu
# Date: 29 April 2019
# https://github.com/trizen
# Given an array of strings, find all the possible ordered concatenations.
# For example, given the array ["1", "2", "3", "4", "5"], there are 16 different ways:
# ["1", "2", "3", "4", "5"]
# ["1", "2", "3", "45"]
# ["1", "2", "34", "5"]
# ["1", "2", "345"]
# ["1", "23", "4", "5"]
# ["1", "23", "45"]
# ["1", "234", "5"]
# ["1", "2345"]
# ["12", "3", "4", "5"]
# ["12", "3", "45"]
# ["12", "34", "5"]
# ["12", "345"]
# ["123", "4", "5"]
# ["123", "45"]
# ["1234", "5"]
# ["12345"]
# In general, for a given array with `n` distict elements, there are `2^(n-1)` possibilities.
# This problem is similar in flavor to the non-greedy text wrapping problem.
# See also:
# https://en.wikipedia.org/wiki/Line_wrap_and_word_wrap
# https://trizenx.blogspot.com/2013/11/smart-word-wrap.html
# Simpler solution:
# https://github.com/trizen/sidef-scripts/blob/master/Math/consecutive_partitions.sf
func create_tries(array) {
var root = []
for i in (^array) {
root << [array.slice(0, i+1)..., __FUNC__(array.slice(i+1))]
}
root
}
func make_paths (array) {
var head = []
while (array) {
break if array[0].kind_of(Array)
head << array.shift
}
var row = []
for path in (array) {
row << Hash(head.join, __FUNC__(path))
}
row ? row : head.join
}
func combine(root, hash) {
var row = []
hash.each{|key,value|
root << key
if (value.kind_of(Array)) {
for item in (value) {
row << __FUNC__(root, item)
}
}
else {
row << (root..., value)
}
root.pop
}
row
}
func normalize(array) {
var normalized = []
for item in (array) {
if (item.kind_of(Array)) {
normalized << __FUNC__(item)...
}
else {
normalized << array
break
}
}
normalized
}
func ordered_concatenations(array) {
var tries = create_tries(array)
var paths = []
for group in (tries) {
paths << make_paths(group)
}
var combinations = []
while (paths) {
if (paths[0].kind_of(Array)) {
paths << paths.shift...
next
}
var path = paths.shift
combinations << combine([], path)
}
normalize(combinations).map { .grep { _ != "" } }
}
var array = %w(1 2 3 4 5)
ordered_concatenations(array).each{ .say }