Skip to content

Instantly share code, notes, and snippets.

@takehiko
Created July 19, 2014 14:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save takehiko/6fe84669773e03414fe2 to your computer and use it in GitHub Desktop.
Save takehiko/6fe84669773e03414fe2 to your computer and use it in GitHub Desktop.
triangle puzzle solver (5 numbers on a side)
#!/usr/bin/env ruby
# -*- coding: utf-8 -*-
# TrianglePuzzleSolver5x5.rb
# by takehikom
# inspired by:
# http://www.ksproj.com/PDF/chirashi201405.pdf
# NOTE: Since we get 4354560 patterns (whereas TrianglePuzzleSolver.rb
# outputs only 960 patterns), it may take several minutes to finish
# "ruby TrianglePuzzleSolver5x5.rb", and you will have gigabytes of
# text file after executing "ruby -d TrianglePuzzleSolver5x5.rb"
# to capture the output.
module TrianglePuzzle
SEQ = (1..8).to_a
class Table
def initialize(ary)
@array = ary.dup
end
attr_accessor :array
def print_table(flag_sum = false)
puts " #{@array[14]}"
puts " #{@array[12]} #{@array[13]}"
puts " #{@array[9]} #{@array[10]} #{@array[11]}"
puts " #{@array[5]} #{@array[6]} #{@array[7]} #{@array[8]}"
puts "#{@array[0]} #{@array[1]} #{@array[2]} #{@array[3]} #{@array[4]}"
if flag_sum
a = get_nine_sums
puts "left[1] = #{a.shift}"
puts "left[2] = #{a.shift}"
puts "left[3] = #{a.shift}"
puts "down[1] = #{a.shift}"
puts "down[2] = #{a.shift}"
puts "down[3] = #{a.shift}"
puts "right[1] = #{a.shift}"
puts "right[2] = #{a.shift}"
puts "right[3] = #{a.shift}"
end
end
def get_nine_sums
[@array[12] + @array[13],
@array[9] + @array[10] + @array[11],
@array[5] + @array[6] + @array[7] + @array[8],
@array[5] + @array[1],
@array[9] + @array[6] + @array[2],
@array[12] + @array[10] + @array[7] + @array[3],
@array[13] + @array[10] + @array[6] + @array[1],
@array[11] + @array[7] + @array[2],
@array[8] + @array[3]]
end
alias :sums :get_nine_sums
def valid?(flag_msg = false)
if @array.length != 15
flag_msg ? "wrong size" : false
elsif @array.map {|item| TrianglePuzzle::SEQ.index(item).nil?}.uniq != [false]
flag_msg ? "invalid value" : false
elsif @array.values_at(0, 1, 2, 3, 4, 6, 7, 10).sort != TrianglePuzzle::SEQ ||
@array.values_at(0, 5, 9, 12, 14, 6, 7, 10).sort != TrianglePuzzle::SEQ ||
@array.values_at(4, 8, 11, 13, 14, 6, 7, 10).sort != TrianglePuzzle::SEQ
flag_msg ? "wrong permutation" : false
else
flag_msg ? "OK" : true
end
end
end
class Searcher
def initialize; end
attr_reader :all, :hash
def start(flag_print = false)
@all = []
@hash = Hash.new
tab_cnt = 0
ary_zero = [0] * 15
TrianglePuzzle::SEQ.permutation do |a|
ary = ary_zero.dup
ary[0] = a[0]
ary[1] = a[1]
ary[2] = a[2]
ary[3] = a[3]
ary[4] = a[4]
ary[6] = a[5]
ary[7] = a[6]
ary[10] = a[7]
(TrianglePuzzle::SEQ - ary.values_at(0, 4, 6, 7, 10)).each do |b|
ary[14] = b
(TrianglePuzzle::SEQ - ary.values_at(0, 14, 6, 7, 10)).permutation do |c|
ary[5] = c[0]
ary[9] = c[1]
ary[12] = c[2]
(TrianglePuzzle::SEQ - ary.values_at(4, 14, 6, 7, 10)).permutation do |d|
ary[8] = d[0]
ary[11] = d[1]
ary[13] = d[2]
tab = TrianglePuzzle::Table.new(ary)
tab_cnt += 1
if flag_print
puts "==== Table #{tab_cnt} ===="
tab.print_table
puts "sums: #{tab.sums.join(', ')}"
puts
end
if !tab.valid?
puts "==== Table #{tab_cnt} ===="
tab.print_table
puts tab.valid?(true)
raise
end
@all << ary
k = tab.sums.join(",")
if @hash.key?(k)
@hash[k] << tab
else
@hash[k] = [tab]
end
end
end
end
end
end
end
end
if __FILE__ == $0
s = TrianglePuzzle::Searcher.new
s.start($DEBUG)
puts "==== 7,11,23,5,20,15,14,17,8 ===="
s.hash["7,11,23,5,20,15,14,17,8"].each do |tab|
tab.print_table(true)
end
puts
if $DEBUG
h = s.hash
h.keys.sort_by {|item| item.split(/,/).map {|num| num.to_i}}.each do |k|
puts "====== values=#{k} ======"
h[k].each_with_index do |tab, i|
puts "(case #{i + 1})"
tab.print_table
end
puts
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment