cem 0.1.2 → 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -1
  3. data/README.md +6 -18
  4. data/cem.gemspec +4 -3
  5. data/examples/aoc2018/.gitignore +2 -0
  6. data/examples/aoc2018/day1.rb +13 -0
  7. data/examples/aoc2018/day10.rb +61 -0
  8. data/examples/aoc2018/day11.rb +66 -0
  9. data/examples/aoc2018/day12.rb +61 -0
  10. data/examples/aoc2018/day13.rb +167 -0
  11. data/examples/aoc2018/day14.rb +31 -0
  12. data/examples/aoc2018/day14_2.rb +71 -0
  13. data/examples/aoc2018/day15.rb +271 -0
  14. data/examples/aoc2018/day16.rb +158 -0
  15. data/examples/aoc2018/day17.rb +203 -0
  16. data/examples/aoc2018/day18.rb +113 -0
  17. data/examples/aoc2018/day18_rspec.rb +131 -0
  18. data/examples/aoc2018/day19.rb +145 -0
  19. data/examples/aoc2018/day1_part2.rb +30 -0
  20. data/examples/aoc2018/day2.rb +20 -0
  21. data/examples/aoc2018/day20.rb +103 -0
  22. data/examples/aoc2018/day21.rb +158 -0
  23. data/examples/aoc2018/day21_v2.rb +137 -0
  24. data/examples/aoc2018/day21_v3.rb +157 -0
  25. data/examples/aoc2018/day21_v4.rb +141 -0
  26. data/examples/aoc2018/day22.rb +212 -0
  27. data/examples/aoc2018/day23.rb +148 -0
  28. data/examples/aoc2018/day24.rb +156 -0
  29. data/examples/aoc2018/day25.rb +52 -0
  30. data/examples/aoc2018/day2_2.rb +27 -0
  31. data/examples/aoc2018/day3.rb +71 -0
  32. data/examples/aoc2018/day4.rb +46 -0
  33. data/examples/aoc2018/day5.rb +23 -0
  34. data/examples/aoc2018/day5_part2.rb +29 -0
  35. data/examples/aoc2018/day6.rb +53 -0
  36. data/examples/aoc2018/day7.rb +110 -0
  37. data/examples/aoc2018/day8.rb +39 -0
  38. data/examples/aoc2018/day8_part2.rb +65 -0
  39. data/examples/aoc2018/day9.rb +51 -0
  40. data/examples/aoc2018/day9_circular.rb +125 -0
  41. data/examples/aoc2018/inputs/day10_input.txt +395 -0
  42. data/examples/aoc2018/inputs/day11_input.txt +1 -0
  43. data/examples/aoc2018/inputs/day12_input.txt +34 -0
  44. data/examples/aoc2018/inputs/day12_input2.txt +16 -0
  45. data/examples/aoc2018/inputs/day13_input.txt +150 -0
  46. data/examples/aoc2018/inputs/day13_test.txt +6 -0
  47. data/examples/aoc2018/inputs/day14_input.txt +1 -0
  48. data/examples/aoc2018/inputs/day15_input.txt +32 -0
  49. data/examples/aoc2018/inputs/day15_input10.txt +32 -0
  50. data/examples/aoc2018/inputs/day15_input11.txt +32 -0
  51. data/examples/aoc2018/inputs/day15_input12.txt +32 -0
  52. data/examples/aoc2018/inputs/day15_input13.txt +32 -0
  53. data/examples/aoc2018/inputs/day15_input14.txt +32 -0
  54. data/examples/aoc2018/inputs/day15_input2.txt +7 -0
  55. data/examples/aoc2018/inputs/day15_input3.txt +9 -0
  56. data/examples/aoc2018/inputs/day15_input4.txt +7 -0
  57. data/examples/aoc2018/inputs/day15_input5.txt +7 -0
  58. data/examples/aoc2018/inputs/day15_input6.txt +7 -0
  59. data/examples/aoc2018/inputs/day15_input7.txt +7 -0
  60. data/examples/aoc2018/inputs/day15_input8.txt +5 -0
  61. data/examples/aoc2018/inputs/day15_input9.txt +7 -0
  62. data/examples/aoc2018/inputs/day15_test.txt +9 -0
  63. data/examples/aoc2018/inputs/day16_input.txt +3865 -0
  64. data/examples/aoc2018/inputs/day17_input.txt +2229 -0
  65. data/examples/aoc2018/inputs/day17_input_test.txt +8 -0
  66. data/examples/aoc2018/inputs/day18_input.txt +50 -0
  67. data/examples/aoc2018/inputs/day18_test.txt +10 -0
  68. data/examples/aoc2018/inputs/day19_input.txt +48 -0
  69. data/examples/aoc2018/inputs/day1_input.txt +955 -0
  70. data/examples/aoc2018/inputs/day20_input.txt +1 -0
  71. data/examples/aoc2018/inputs/day21_input.txt +32 -0
  72. data/examples/aoc2018/inputs/day22_input.txt +2 -0
  73. data/examples/aoc2018/inputs/day23_input.txt +1000 -0
  74. data/examples/aoc2018/inputs/day23_input2.txt +9 -0
  75. data/examples/aoc2018/inputs/day24_input.txt +24 -0
  76. data/examples/aoc2018/inputs/day25_input.txt +1483 -0
  77. data/examples/aoc2018/inputs/day2_input.txt +250 -0
  78. data/examples/aoc2018/inputs/day3_input.txt +1233 -0
  79. data/examples/aoc2018/inputs/day4_input.txt +1140 -0
  80. data/examples/aoc2018/inputs/day5_input.txt +1 -0
  81. data/examples/aoc2018/inputs/day6_input.txt +50 -0
  82. data/examples/aoc2018/inputs/day7_input.txt +101 -0
  83. data/examples/aoc2018/inputs/day8_input.txt +1 -0
  84. data/examples/aoc2018/inputs/day9_input.txt +1 -0
  85. data/lib/cem/ccommon.rb +51 -6
  86. data/lib/cem/cflame/popen.rb +89 -0
  87. data/lib/cem/cflame.rb +2 -0
  88. data/lib/cem/cruzzles.rb +198 -50
  89. data/lib/cem/version.rb +1 -1
  90. data/lib/cem.rb +0 -6
  91. metadata +88 -22
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7d56d8ba91aab41f5e12070a9f821516b8f69d626d3ffd7261dca402c41768ba
4
- data.tar.gz: 513114a63b34c7375339e4eb17d931bc7925bb068495c4726a6577e98c0ebc7a
3
+ metadata.gz: eb4683b5fc26b935c95d45b05a77e44c859880c4b0eb6b9424555fb55819582c
4
+ data.tar.gz: 3183e62b7576af9229f1a6c3315df529b19655b5ace714d8ba0e8ce32769ac60
5
5
  SHA512:
6
- metadata.gz: 55106e14c662cec3b4ffc68c6e0bb5775405fadbb61d1fd2d4611becd38d7cf55445e8a7872107797df5aaa4da18656419dbf0ed37eb676dc10a2184aa7168f1
7
- data.tar.gz: f8f56d39752badb44074162e20452814937bd40ee44bd0e22ea777bd775f5c830e25768ec21ca104310efa84bb3679e868d99af9a674a907807e479efc43cdf8
6
+ metadata.gz: bb4a8e8b37769607711c2747fdaf975a3abfa04793ad5739bc5067a215953b113aa8ecb96f4ed603113c5e32d193853a5fd1be680e637c4ad6e40a3d82619d70
7
+ data.tar.gz: bc6f46c74b61524113bb6071e635eb71eb3799d1888a2f78879441e73aebaaa7d301f785b9a48d9bc9a2eebeb134c35e129a981bca327bc1f6a59fe5e69b6849
data/.gitignore CHANGED
@@ -54,4 +54,5 @@ Gemfile.lock
54
54
  .rvmrc
55
55
 
56
56
  # Used by RuboCop. Remote config files pulled in from inherit_from directive.
57
- # .rubocop-https?--*
57
+ # .rubocop-https?--
58
+ .idea/
data/README.md CHANGED
@@ -4,18 +4,6 @@ This gem is an assorted collection of common helpers that I use in a lot of proj
4
4
 
5
5
  ## Installation
6
6
 
7
- Add this line to your application's Gemfile:
8
-
9
- ```ruby
10
- gem 'cem'
11
- ```
12
-
13
- And then execute:
14
-
15
- $ bundle
16
-
17
- Or install it yourself as:
18
-
19
7
  $ gem install cem
20
8
 
21
9
  ## Usage
@@ -26,19 +14,19 @@ Key things includes:
26
14
 
27
15
  ### crequire
28
16
 
29
- crequire is a replacement for require for situations where bundler would be overkill. It solves the frustration of having to manually install gems to run a particular ruby script which requires other gems.
17
+ `crequire` is a replacement for `require` for situations where bundler would be overkill. It solves the frustration of having to manually install gems to run a particular ruby script which requires other gems.
30
18
 
31
- For example when you want to require 'qml' from the 'ruby-qml' gem, use the following line:
19
+ For example when you want to require `qml` from the `ruby-qml` gem, use the following line:
32
20
 
33
21
  ```
34
22
  crequire 'qml', 'ruby-qml'
35
23
  ```
36
24
 
37
- This will attempt to require qml and if it can't be found in the local RubyGems, then it will try to `gem install ruby-qml`
25
+ This will attempt to require `qml` and if it can't be found in the local RubyGems, then it will try to `gem install ruby-qml`
38
26
 
39
27
  ### Array::with_progress
40
28
 
41
- Monkey patches array to return an enumeration which prints progress while lazy evaluating the enumeration.
29
+ Monkey patches `Array` to return an enumeration which prints progress while lazy evaluating the enumeration.
42
30
 
43
31
  ```
44
32
  require 'cem'
@@ -59,7 +47,7 @@ Defines integer based `Point2D`, `Seg2D` (line segment), `Dir2D` (relative direc
59
47
 
60
48
  ## Development
61
49
 
62
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
50
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rspec` to run the tests.
63
51
 
64
52
  To install this gem onto your local machine, run `bundle exec rake install`.
65
53
 
@@ -71,7 +59,7 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/coezbe
71
59
 
72
60
  ## License
73
61
 
74
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
62
+ The gem is available as permissive open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
75
63
 
76
64
  ## What's with the name?
77
65
 
data/cem.gemspec CHANGED
@@ -35,9 +35,10 @@ Gem::Specification.new do |spec|
35
35
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
36
36
  spec.require_paths = ["lib"]
37
37
 
38
- spec.add_development_dependency "bundler", "~> 1.17"
39
- spec.add_development_dependency "rake", "~> 10.0"
38
+ spec.add_development_dependency "bundler", "~> 2.1" # Was 1.17
39
+ spec.add_development_dependency "rake", "~> 13.0" # Was: 10.0
40
40
  spec.add_development_dependency "rspec", "~> 3.0"
41
41
 
42
- spec.add_runtime_dependency 'flammarion', '~> 0.3'
42
+ # Flammarion is not a runtime dependency, but rather optional
43
+ # spec.add_runtime_dependency 'flammarion', '~> 0.3'
43
44
  end
@@ -0,0 +1,2 @@
1
+ problems/
2
+ temps/
@@ -0,0 +1,13 @@
1
+
2
+ #
3
+ # https://adventofcode.com/2018/day/1 Part 1
4
+ #
5
+ # Does not use any cem functions \o/
6
+ #
7
+
8
+ result = 0
9
+ File.read("inputs/day1_input.txt").each_line { |line|
10
+ result += line.to_i
11
+ }
12
+
13
+ puts result
@@ -0,0 +1,61 @@
1
+
2
+ #
3
+ # https://adventofcode.com/2018/day/10 part 1 and part 2
4
+ #
5
+ # Demonstrates use of
6
+ # - Point2D#area returns x*y as if the given point was a representing a rectangle starting at 0,0
7
+ # - Point2D#+ and #- allow to use normal vector math on points
8
+ # - Grid.from_points allows to build a Grid view of a set of points
9
+ #
10
+ # Also did you know that:
11
+ # - Numeric#step can receive a block directly to implement an infinite for loop?
12
+ # - Array#minmax => Find min and max from an array
13
+ #
14
+
15
+ require 'cem'
16
+
17
+ input = File.readlines("inputs/day10_input.txt", chomp: true)
18
+
19
+ data = []
20
+
21
+ input.each { |line|
22
+
23
+ if line =~ /^position=<\s*(-?\d+),\s*(-?\d+)> velocity=<\s*(-?\d+),\s*(-?\d+)>$/
24
+ p1 = $1.to_i
25
+ p2 = $2.to_i
26
+ v1 = $3.to_i
27
+ v2 = $4.to_i
28
+
29
+ data << [Point2D.new(p1,p2), Point2D.new(v1,v2)]
30
+ else
31
+ raise line
32
+ end
33
+ }
34
+
35
+ lastSize = nil
36
+
37
+ # Count iterations from 0, because we need to return the iteration number preceeding the last.
38
+ 0.step { |iter|
39
+
40
+ # Apply velocity to all points
41
+ data.map! { |p, v| [p + v, v] }
42
+
43
+ min, max = data.map { |p, v| p }.minmax
44
+
45
+ size = (max - min).area
46
+
47
+ # Terminate the search when the area of all points starts growing again.
48
+ if lastSize && size > lastSize
49
+
50
+ # Go back one iteration
51
+ puts "Word:\n" + Grid.from_points(data.map { |p, v| p - v }).to_s
52
+
53
+ puts "Iterations until word: #{iter}"
54
+
55
+ return
56
+
57
+ end
58
+
59
+ lastSize = size
60
+ }
61
+
@@ -0,0 +1,66 @@
1
+
2
+ #
3
+ # https://adventofcode.com/2018/day/11 part 1 and part 2
4
+ #
5
+ # Does not use any cem functions \o/
6
+ #
7
+
8
+ input = 5177
9
+
10
+ levels = [0] * (300 * 300)
11
+
12
+ (1..300).each { |x|
13
+ (1..300).each { |y|
14
+
15
+ rackId = ( x) + 10
16
+ powerLevel = rackId * ( y)
17
+ powerLevel += input
18
+ powerLevel *= rackId
19
+ powerLevel /= 100
20
+ powerLevel -= powerLevel / 10 * 10
21
+ powerLevel -= 5
22
+
23
+ levels[y * 300 + x] = powerLevel
24
+ }
25
+ }
26
+
27
+ max = 0
28
+ (1..300).each { |gridsize|
29
+
30
+ local_max = nil
31
+ local = nil
32
+ (1..300-gridsize).each { |x|
33
+ (1..300-gridsize).each { |y|
34
+
35
+ sum = 0
36
+
37
+ (0..gridsize-1).each { |dx|
38
+ (0..gridsize-1).each { |dy|
39
+
40
+ sum += levels[(dy + y) * 300 + dx + x]
41
+ }
42
+ }
43
+
44
+ if !local_max || sum > local_max
45
+ local = "#{x}, #{y}, #{gridsize}: #{sum}"
46
+ local_max = sum
47
+ end
48
+ }
49
+ }
50
+
51
+ if gridsize == 3
52
+ puts "Part 1 result:"
53
+ end
54
+
55
+ print local
56
+
57
+ if local_max > max
58
+ puts "***"
59
+ max = local_max
60
+ else
61
+ puts
62
+ puts "Previous data is max"
63
+ exit
64
+ end
65
+ }
66
+
@@ -0,0 +1,61 @@
1
+
2
+ #
3
+ # https://adventofcode.com/2018/day/12 part 1 and part 2
4
+ #
5
+ # Does not use any cem functions \o/
6
+ #
7
+
8
+ input = {}
9
+
10
+ start = ""
11
+ File.readlines("inputs/day12_input.txt", chomp: true).each { |line|
12
+
13
+ if line =~ /^initial state\: (.*)$/
14
+ start = $1
15
+ end
16
+
17
+ if line =~ /^(.....) => (.)$/
18
+ input[$1] = $2
19
+ end
20
+
21
+ }
22
+
23
+ result = ''
24
+ previous_score = nil
25
+ delta = nil
26
+ offset = 0
27
+ max_gen = 50000000000
28
+
29
+ (1..max_gen).each { |gen|
30
+
31
+ start = "...." + start + "...."
32
+ offset -= 2
33
+
34
+ result = ''
35
+ (0...start.length - 4).each { |i|
36
+ result += input.has_key?(start[i,5]) ? input[start[i,5]] : '.'
37
+ }
38
+
39
+ score = 0
40
+ (0...result.length).each { |i|
41
+ score += i + offset if result[i] == '#'
42
+ }
43
+
44
+ # puts score
45
+ if gen == 20
46
+ puts "Part 1: Generation #{gen} has score #{score}"
47
+ end
48
+
49
+ if delta && (score - previous_score == delta)
50
+ puts
51
+ puts "Part 2: Generation #{gen} has score #{score} with same delta as before (#{delta})."
52
+ puts "If continued to gen #{max_gen} the score would be #{(max_gen - gen) * delta + score}"
53
+ exit
54
+ end
55
+
56
+ delta = score - previous_score if previous_score
57
+ previous_score = score
58
+
59
+ start = result
60
+ }
61
+
@@ -0,0 +1,167 @@
1
+
2
+ #
3
+ # https://adventofcode.com/2018/day/13 part 1 and 2
4
+ #
5
+ # Demonstrates Point2D. Certainly could use Grid!
6
+
7
+ require 'cem'
8
+
9
+ Cart = Struct.new("Cart", :dir, :pos, :history)
10
+ carts = []
11
+ lines = []
12
+
13
+ # Read board
14
+ File.readlines("inputs/day13_input.txt", chomp: true).each { |line|
15
+ lines << line.rstrip
16
+ }
17
+
18
+ # Read carts
19
+ lines.each_with_index { |l, y|
20
+ l.chars.each_with_index { |c, x|
21
+ case c
22
+ when '^', 'v'
23
+ lines[y][x] = '|'
24
+ carts << Cart.new(c, Point2D.new(x,y), 2)
25
+ when '>', '<'
26
+ lines[y][x] = '-'
27
+ carts << Cart.new(c, Point2D.new(x,y), 2)
28
+ end
29
+ }
30
+ }
31
+
32
+ def printBoard(lines, carts)
33
+
34
+ lines.each_with_index { |l, y|
35
+ l.chars.each_with_index { |c, x|
36
+
37
+ a = carts.find { |cart| cart.pos == Point2D.new(x,y) }
38
+ if a
39
+ print a.dir
40
+ else
41
+ print c
42
+ end
43
+ }
44
+ print "\n"
45
+ }
46
+ end
47
+
48
+ generation = 0
49
+ first = true
50
+
51
+ loop do
52
+
53
+ generation += 1
54
+
55
+ if carts.size == 1
56
+ puts "Last crash at: #{carts[0].pos}"
57
+ exit
58
+ end
59
+
60
+ # system "cls"
61
+ # puts generation
62
+ # puts carts.inspect
63
+ # printBoard(lines, carts)
64
+ # gets
65
+
66
+ carts.sort_by { |cart| cart.pos.y * 10000 + cart.pos.x }.each { |cart|
67
+
68
+ cart.pos += Point2D.from_s(cart.dir)
69
+
70
+ if crash = carts.find { |c2| cart != c2 && cart.pos == c2.pos }
71
+ if first
72
+ puts "First crash at: #{cart.pos}"
73
+ first = false
74
+ end
75
+
76
+ carts.delete(crash)
77
+ carts.delete(cart)
78
+
79
+ end
80
+
81
+ track = lines[cart.pos.y][cart.pos.x]
82
+
83
+ case cart.dir
84
+
85
+ when '>'
86
+
87
+ case track
88
+ when '\\'
89
+ cart.dir = 'v'
90
+ when '/'
91
+ cart.dir = '^'
92
+ when '+'
93
+
94
+ cart.history = (cart.history + 1) % 3
95
+ case cart.history
96
+ when 1
97
+ # nothing
98
+ when 2
99
+ cart.dir = 'v'
100
+ when 0
101
+ cart.dir = '^'
102
+ end
103
+
104
+ end
105
+
106
+ when '<'
107
+ case track
108
+ when '\\'
109
+ cart.dir = '^'
110
+ when '/'
111
+ cart.dir = 'v'
112
+ when '+'
113
+
114
+ cart.history = (cart.history + 1) % 3
115
+ case cart.history
116
+ when 1
117
+ # nothing
118
+ when 2
119
+ cart.dir = '^'
120
+ when 0
121
+ cart.dir = 'v'
122
+ end
123
+
124
+ end
125
+ when '^'
126
+ case track
127
+ when '\\'
128
+ cart.dir = '<'
129
+ when '/'
130
+ cart.dir = '>'
131
+ when '+'
132
+
133
+ cart.history = (cart.history + 1) % 3
134
+ case cart.history
135
+ when 1
136
+ # nothing
137
+ when 2
138
+ cart.dir = '>'
139
+ when 0
140
+ cart.dir = '<'
141
+ end
142
+
143
+ end
144
+ when 'v'
145
+ case track
146
+ when '\\'
147
+ cart.dir = '>'
148
+ when '/'
149
+ cart.dir = '<'
150
+ when '+'
151
+
152
+ cart.history = (cart.history + 1) % 3
153
+ case cart.history
154
+ when 1
155
+ # nothing
156
+ when 2
157
+ cart.dir = '<'
158
+ when 0
159
+ cart.dir = '>'
160
+ end
161
+
162
+ end
163
+ end
164
+ }
165
+
166
+
167
+ end
@@ -0,0 +1,31 @@
1
+
2
+ #
3
+ # https://adventofcode.com/2018/day/14 part 1
4
+ #
5
+ # Does not use any cem functions \o/
6
+
7
+ recipes = 30121
8
+
9
+ nexta = 3
10
+ storage = [3, 7]
11
+ elves = [0, 1]
12
+
13
+ i = 2
14
+ while i < recipes + 10
15
+
16
+ r = storage[elves[0]] + storage[elves[1]]
17
+
18
+ r.to_s.chars.each { |c|
19
+ storage << c.to_i
20
+ i += 1
21
+
22
+ if i == recipes + 10
23
+ break;
24
+ end
25
+ }
26
+
27
+ elves[0] = (1 + elves[0] + storage[elves[0]]) % storage.size
28
+ elves[1] = (1 + elves[1] + storage[elves[1]]) % storage.size
29
+ end
30
+
31
+ puts storage[-10,15].map { |i| i.to_s}.join
@@ -0,0 +1,71 @@
1
+
2
+ #
3
+ # https://adventofcode.com/2018/day/14 part 2
4
+ #
5
+ # Does not use any cem functions \o/
6
+
7
+
8
+ #recipes = "51589"
9
+ #recipes = "59414"
10
+ #recipes = "652601"
11
+
12
+ recipes = "030121"
13
+
14
+ r2 = recipes.chars.map {|c| c.to_i}
15
+
16
+ storage = [0] * 100000000
17
+ storage[0] = 3
18
+ storage[1] = 7
19
+
20
+ e0 = 0
21
+ e1 = 1
22
+
23
+ comp = [0] * r2.length
24
+
25
+ i = 2
26
+ while true
27
+
28
+ puts i if i % 100000 == 0
29
+
30
+ s0 = storage[e0]
31
+ s1 = storage[e1]
32
+
33
+ r = s0 + s1
34
+
35
+ if r >= 10
36
+ storage[i] = 1
37
+ i+=1
38
+
39
+ comp << 1
40
+ comp = comp.drop(1)
41
+
42
+ if comp == r2
43
+ puts i - recipes.length
44
+ exit
45
+ end
46
+ storage[i] = r - 10
47
+ i+=1
48
+ comp << r - 10
49
+ comp = comp.drop(1)
50
+
51
+ if comp == r2
52
+ puts i - recipes.length
53
+ exit
54
+ end
55
+ else
56
+ storage[i] = r
57
+ i+=1
58
+ comp << r
59
+ comp = comp.drop(1)
60
+
61
+ if comp == r2
62
+ puts i - recipes.length
63
+ exit
64
+ end
65
+
66
+ end
67
+
68
+ e0 = (1 + e0 + s0) % i
69
+ e1 = (1 + e1 + s1) % i
70
+ end
71
+