Skip to content

Commit b51c71f

Browse files
authored
Merge branch 'master' into hacktober-add-queue
2 parents 0ec2163 + af538e7 commit b51c71f

File tree

15 files changed

+707
-0
lines changed

15 files changed

+707
-0
lines changed
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
# frozen_string_literal: true
2+
# Conway's Game of Life
3+
#
4+
# Author: Sebastian Sangervasi
5+
6+
class GameOfLife
7+
def self.from_str(string)
8+
non_empty_lines =
9+
string
10+
.split("\n")
11+
.lazy
12+
.map(&:strip)
13+
.reject(&:empty?)
14+
15+
parsed_grid = non_empty_lines.lazy.map do |line|
16+
lazy_line = line.split('').lazy.map do |char|
17+
Cell.from_str(char)
18+
end
19+
lazy_line.to_a
20+
end
21+
22+
new(grid: parsed_grid.to_a)
23+
end
24+
25+
def initialize(grid:)
26+
@grid = grid
27+
end
28+
29+
attr_reader :grid
30+
31+
def height
32+
grid.size
33+
end
34+
35+
def width
36+
grid.first&.size || 0
37+
end
38+
39+
def to_s
40+
str_rows = grid.map do |row|
41+
row.map(&:to_s).join
42+
end
43+
str_rows.join("\n")
44+
end
45+
46+
def next_generation
47+
lazy_grid = grid_with_live_neighbor_counts.map do |row|
48+
lazy_row = row.map do |cell, neighbor_count|
49+
cell.next_state(neighbor_count)
50+
end
51+
lazy_row.to_a
52+
end
53+
54+
self.class.new(grid: lazy_grid.to_a)
55+
end
56+
57+
private
58+
59+
def grid_with_live_neighbor_counts
60+
grid.lazy.each_with_index.map do |row, row_index|
61+
row.lazy.each_with_index.map do |cell, cell_index|
62+
[cell, count_live_neighbors(row_index, cell_index)]
63+
end
64+
end
65+
end
66+
67+
def count_live_neighbors(row, col)
68+
neighbor_coords = neighbor_directions.map do |d_row, d_col|
69+
[row + d_row, col + d_col]
70+
end
71+
neighbors = neighbor_coords.lazy.map do |row, col|
72+
get_cell(row, col, default: Dead.new)
73+
end
74+
neighbors.map { |cell| cell.alive? ? 1 : 0 }.sum
75+
end
76+
77+
def neighbor_directions
78+
@neighbor_directions ||= begin
79+
directions_1D = [-1, 0, 1]
80+
directions_1D
81+
.product(directions_1D)
82+
.reject { |pair| pair == [0, 0] }
83+
end
84+
end
85+
86+
def get_cell(row, col, default: nil)
87+
is_within_rows = (0...height).cover?(row)
88+
is_within_cols = (0...width).cover?(col)
89+
return grid[row][col] if is_within_rows && is_within_cols
90+
91+
default
92+
end
93+
end
94+
95+
class Cell
96+
def self.from_str(string)
97+
return Live.new if string == Live::STRING_FORM
98+
Dead.new
99+
end
100+
101+
def to_s
102+
self.class::STRING_FORM
103+
end
104+
end
105+
106+
class Dead < Cell
107+
STRING_FORM = '·'
108+
109+
def alive?
110+
false
111+
end
112+
113+
def next_state(neighbor_count)
114+
return Live.new if neighbor_count == 3
115+
Dead.new
116+
end
117+
end
118+
119+
class Live < Cell
120+
STRING_FORM = '0'
121+
122+
def alive?
123+
true
124+
end
125+
126+
def next_state(neighbor_count)
127+
return Live.new if (2..3).cover?(neighbor_count)
128+
Dead.new
129+
end
130+
end
131+
132+
def glider_example
133+
seed_str = <<~GLIDER
134+
··0····
135+
0·0····
136+
·00····
137+
·······
138+
·······
139+
·······
140+
GLIDER
141+
seed_game = GameOfLife.from_str(seed_str)
142+
num_gens = 15
143+
puts <<~HEADER
144+
=========================
145+
| Conway's Game of Life |
146+
=========================
147+
Starting with seed: "Glider"
148+
Running for #{num_gens} generations.
149+
HEADER
150+
latest_generation = seed_game
151+
(1..num_gens).map do |gen_num|
152+
puts "Generation #{gen_num}:"
153+
puts latest_generation
154+
latest_generation = latest_generation.next_generation
155+
end
156+
end
157+
158+
if __FILE__ == $0
159+
glider_example
160+
end

ciphers/encryptor.rb

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
CIPHER_MAP =
2+
{'a' => 'n', 'b' => 'o', 'c' => 'p', 'd' => 'q',
3+
'e' => 'r', 'f' => 's', 'g' => 't', 'h' => 'u',
4+
'i' => 'v', 'j' => 'w', 'k' => 'x', 'l' => 'y',
5+
'm' => 'z', 'n' => 'a', 'o' => 'b', 'p' => 'c',
6+
'q' => 'd', 'r' => 'e', 's' => 'f', 't' => 'g',
7+
'u' => 'h', 'v' => 'i', 'w' => 'j', 'x' => 'k',
8+
'y' => 'l', 'z' => 'm'}
9+
10+
puts gets
11+
.chomp
12+
.chars
13+
.map { |letter| CIPHER_MAP[letter.downcase] }.join

cryptography/ed25519.rb

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
require 'openssl'
2+
3+
# Port of http://ed25519.cr.yp.to/python/ed25519.py
4+
5+
@b = 256
6+
@q = 2**255 - 19
7+
@l = 2**252 + 27742317777372353535851937790883648493
8+
9+
def H(m)
10+
OpenSSL::Digest::SHA512.digest(m)
11+
end
12+
13+
def expmod(b,e,m)
14+
return 1 if e == 0
15+
t = expmod(b,e/2,m)**2 % m
16+
t = (t*b) % m if e & 1 != 0
17+
return t
18+
end
19+
20+
def inv(x)
21+
expmod(x,@q-2,@q)
22+
end
23+
24+
@d = -121665 * inv(121666)
25+
@I = expmod(2,(@q-1)/4,@q)
26+
27+
def xrecover(y)
28+
xx = (y*y-1) * inv(@d*y*y+1)
29+
x = expmod(xx,(@q+3)/8,@q)
30+
x = (x*@I) % @q if (x*x - xx) % @q != 0
31+
x = @q-x if x % 2 != 0
32+
x
33+
end
34+
35+
@By = 4 * inv(5)
36+
@Bx = xrecover(@By)
37+
@B = [@Bx % @q,@By % @q]
38+
39+
def edwards(_P,_Q)
40+
x1 = _P[0]
41+
y1 = _P[1]
42+
x2 = _Q[0]
43+
y2 = _Q[1]
44+
x3 = (x1*y2+x2*y1) * inv(1+@d*x1*x2*y1*y2)
45+
y3 = (y1*y2+x1*x2) * inv(1-@d*x1*x2*y1*y2)
46+
return [x3 % @q,y3 % @q]
47+
end
48+
49+
def scalarmult(_P,e)
50+
return [0,1] if e == 0
51+
_Q = scalarmult(_P,e/2)
52+
_Q = edwards(_Q,_Q)
53+
_Q = edwards(_Q,_P) if e & 1 != 0
54+
return _Q
55+
end
56+
57+
def encodeint(y)
58+
bits = (0...@b).map{ |i| (y >> i) & 1}
59+
(0...@b/8).map{ |i|(0...8).map { |j| bits[i * 8 + j] << j}.sum.chr }.join
60+
end
61+
62+
def encodepoint(_P)
63+
x = _P[0]
64+
y = _P[1]
65+
bits = (0...@b-1).map{|i| (y >> i ) & 1}.concat([x & 1])
66+
(0...@b/8).map {|i|(0...8).map {|j| bits[i * 8 + j] << j}.sum.chr }.join
67+
end
68+
69+
def bit(h,i)
70+
((h[i/8]).ord >> (i%8)) & 1
71+
end
72+
73+
def publickey(sk)
74+
h = H(sk)
75+
a = 2**(@b-2) + (3...@b-2).map{|i| 2**i * bit(h,i)}.sum
76+
_A = scalarmult(@B,a)
77+
encodepoint(_A)
78+
end
79+
80+
def Hint(m)
81+
h = H(m)
82+
(0...2*@b).map {|i| 2**i * bit(h,i)}.sum
83+
end
84+
85+
def signature(m,sk,pk)
86+
h = H(sk)
87+
a = 2**(@b-2) + (3...@b-2).map{|i| 2**i * bit(h,i)}.sum
88+
r = Hint((@b/8...@b/4).map { |i| h[i]}.join + m)
89+
_R = scalarmult(@B,r)
90+
_S = (r + Hint(encodepoint(_R) + pk + m) * a) % @l
91+
encodepoint(_R) + encodeint(_S)
92+
end
93+
94+
def isoncurve(_P)
95+
x = _P[0]
96+
y = _P[1]
97+
(-x*x + y*y - 1 - @d*x*x*y*y) % @q == 0
98+
end
99+
100+
def decodeint(s)
101+
(0...@b).map{|i| 2**i * bit(s,i)}.sum
102+
end
103+
104+
def decodepoint(s)
105+
y = (0...@b-1).map{|i| 2**i * bit(s,i)}.sum
106+
x = xrecover(y)
107+
x = @q - x if x & 1 != bit(s,@b-1)
108+
_P = [x,y]
109+
raise ArgumentError, "decoding point that is not on curve" unless isoncurve(_P)
110+
_P
111+
end
112+
113+
def checkvalid(s,m,pk)
114+
raise ArgumentError, "signature length is wrong" if s.length != @b/4
115+
raise ArgumentError, "public-key length is wrong "if pk.length != @b/8
116+
_R = decodepoint(s[0..@b/8])
117+
_A = decodepoint(pk)
118+
_S = decodeint(s[@b/8..@b/4])
119+
h = Hint(encodepoint(_R) + pk + m)
120+
raise "Signature does not pass verifiction" if scalarmult(@B,_S) != edwards(_R,scalarmult(_A,h))
121+
end

0 commit comments

Comments
 (0)