#!/usr/home/robinson/Dist/ruby-1.6.2/ruby

class Spindle
	def initialize(size, number)
		@stack = []
		for i in 0...size
			@stack += [nil]
		end
		@index = 0
		@number = number
	end
	def number
		return @number
	end
	def push(disc)
		if @index >= @stack.length
			print "Abort: Push over top\n"
			printme()
			exit
		elsif @index == 0
			@stack[@index] = disc
		elsif @stack[@index-1].size < disc.size
			print "Abort: Push on smaller disc\n"
			printme
			exit
		else
			@stack[@index] = disc
		end
		@index += 1
		disc.place(self)
	end
	def pop
		if @index == 0
			print "Abort: Pop off empty spindle"
			printme
			exit
		else
			@index -= 1
			return @stack[@index]
		end
	end
	def bottom
		if @index > 0
			return @stack[0]
		else
			return nil
		end
	end
	def over(disc)
		for i in 0...@index-1
			if @stack[i] == disc
				return @stack[i+1]
			end
		end
		return nil
	end
	def under(disc)
		retval = nil
		i = @index-1
		while i >= 0
			if @stack[i].size < disc.size
				retval = @stack[i]
			end
			i -= 1
		end
		return retval
	end
	def printme
		print "-> "
		for i in 0...@index
			printf("%2d ", @stack[i].size)
		end
		print "\n"
	end
end

class Disc
	def initialize(size)
		@size = size
	end
	def place(spindle)
		@spindle = spindle
	end
	def size
		return @size
	end
	def spindle
		return @spindle
	end
	def moveto(spindle)
		third = $spindles[6 - @spindle.number - spindle.number - 1]
		over = @spindle.over(self)
		under = spindle.under(self)
		if over or under
			if over and under
				if over.size > under.size
					over.moveto(third)
				else
					under.moveto(third)
				end
			elsif over
				over.moveto(third)
			elsif under
				under.moveto(third)
			end
		else
			@spindle.pop
			spindle.push(self)
			return
		end
		moveto(spindle)
		return
	end
end

size = Integer(ARGV[0])
$spindles = [Spindle.new(size, 1), Spindle.new(size, 2), Spindle.new(size, 3)]
i = size
while i > 0
	$spindles[0].push(Disc.new(i))
	i -= 1
end
one = $spindles[0].bottom
three = $spindles[2].bottom
while one or three
	if one and three
		if one.size > three.size
			one.moveto($spindles[1])
		else
			three.moveto($spindles[1])
		end
	elsif one
		one.moveto($spindles[1])
	elsif three
		three.moveto($spindles[1])
	end
	one = $spindles[0].bottom
	three = $spindles[2].bottom
end
$spindles[0].printme
$spindles[1].printme
$spindles[2].printme
