Skip to content

Instantly share code, notes, and snippets.

@mvw
Last active January 17, 2020 01:37

Revisions

  1. mvw revised this gist Sep 4, 2015. No changes.
  2. mvw revised this gist Sep 4, 2015. 1 changed file with 5 additions and 1 deletion.
    6 changes: 5 additions & 1 deletion cuberots.rb
    Original file line number Diff line number Diff line change
    @@ -174,7 +174,7 @@ def number_to_names(s)
    p
    end

    n = 8
    n = 5
    k_show = 20
    k_last = 4**n - 1 - k_show

    @@ -188,13 +188,17 @@ def number_to_names(s)
    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

  3. mvw created this gist Sep 4, 2015.
    201 changes: 201 additions & 0 deletions cuberots.rb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,201 @@
    #!/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 = 8
    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
    known, rot_n = $rots.add(rot)
    if known
    rot = rot_n
    else
    show = true
    end
    end
    puts "k = #{k+1}: #{s} #{p} -> #{rot}" if show || k >= k_last
    end

    puts "rots = #{$rots}"