Skip to content

Instantly share code, notes, and snippets.

@mvw
Last active January 17, 2020 01:37
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mvw/1d7bf6ed0a9f6cfef778 to your computer and use it in GitHub Desktop.
Save mvw/1d7bf6ed0a9f6cfef778 to your computer and use it in GitHub Desktop.
#!/usr/bin/ruby
# cuberots.rb
class Permutation
attr_accessor :s
attr_accessor :h
def initialize(s = '12345678')
@s = s
a = @s.split('')
@h = Hash.new
i = '1'
a.each do |c|
@h[i] = c
i.next!
end
end
def to_s
return @s
end
# composition f*g means (f*g)(x) = f(g(x))
def *(g)
s = ''
c = '1'
8.times do
s += @h[g.h[c]]
c.next!
end
Permutation.new(s)
end
end
class Rotation
attr_accessor :name
attr_accessor :perm
def initialize(name = 'e', perm_s = '12345678')
@name = name
@perm = Permutation.new(perm_s)
end
def to_s
@name + '=' + @perm.to_s
end
# composition f*g means (f*g)(x) = f(g(x))
def *(g)
Rotation.new(@name + g.name, (@perm * g.perm).s)
end
# exponentiation
def **(k)
case
when k < 0
nil # TODO find out inverse
when k == 0
$e
when k == 1
self
else
self * (self**(k-1))
end
end
# name to rotation
def self.from_name(c)
case
when c == 'e'
$e
when c == 'x'
$x
when c == 'y'
$y
when c == 'z'
$z
else
nil
end
end
end
class Rots
def initialize
@h = Hash.new
end
def to_s
s = "[\n"
k = 0
@h.each do |name, value|
k += 1
rot, aliases = value
s += " k = #{k}: #{rot} #{aliases}\n"
end
s += "]\n"
s
end
# returns if known (and normalized version)
def add(rot)
rot_s = rot.perm.s
entry = @h[rot_s]
if entry.nil?
@h[rot_s] = [rot, []]
return false, nil
end
name = rot.name
rot_n, aliases = entry
if name == rot_n.name
return true, rot_n
end
if aliases.member?(name)
return true, rot_n
end
# new alias
aliases << name
@h[rot_s] = [rot_n, aliases]
return true, rot_n
end
end
# base rotations
# / 8 7 / 8 7
# / 5 6 / 5 6
# 4 3 / -> 4 3 /
# 1 2/ 1 2/
$e = Rotation.new('e', '12345678')
# / 8 7 / 5 6
# / 5 6 / 1 2
# 4 3 / -> 8 7 /
# 1 2/ 4 3/
$x = Rotation.new('x', '56218734')
# / 8 7 / 5 8
# / 5 6 / 6 7
# 4 3 / -> 1 4 /
# 1 2/ 2 3/
$y = Rotation.new('y', '41238567')
# / 8 7 / 7 3
# / 5 6 / 6 2
# 4 3 / -> 8 4 /
# 1 2/ 5 1/
$z = Rotation.new('z', '26731584')
$rots = Rots.new
$rots.add($e)
$rots.add($x)
$rots.add($y)
$rots.add($z)
puts "rots = #{$rots}"
# translate digits into base rotations
def number_to_names(s)
p = s.dup
p.gsub!(/0/, 'e')
p.gsub!(/1/, 'x')
p.gsub!(/2/, 'y')
p.gsub!(/3/, 'z')
p
end
n = 5
k_show = 20
k_last = 4**n - 1 - k_show
# iterate in base 4 up to length n
(4**n).times do |k|
s = k.to_s(4)
p = number_to_names(s)
# parse string, compose rotations
rot = $e
show = k < k_show ? true : false
a = p.split('').reverse
a.each do |c|
rot = Rotation.from_name(c) * rot
# add (and normalize) intermediate results
known, rot_n = $rots.add(rot)
if known
rot = rot_n
else
show = true
end
end
# try to add the original alias
rot_orig = Rotation.new(p, rot.perm.s)
$rots.add(rot_orig)
puts "k = #{k+1}: #{s} #{p} -> #{rot}" if show || k >= k_last
end
puts "rots = #{$rots}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment