This one will "possible" find solution for "cycle pattern".
It simply uses JC Warnsdorff (1823) rule,
so, it may not always find solution.

After my test, it does find cycle solutin for n = 5, 6, 15, 16, 22, 24, 25 ....
(Of couse, I could try add brute-forcing, but don't have time to play
with it now... )


class PenAndPaperGame2
  MOVES = [[3,0], [-3,0], [0,3], [0,-3], [2,2], [2,-2], [-2,2], [-2,-2]]
  attr_reader :found

  def initialize(size)
    @size = size
    @board = Array.new(@size) { Array.new(@size) }
    @found = false
  end

  def to_s
    return "No soultion" unless @found
    digits = (@size * @size).to_s.size
    " #{'-' * (digits+2) * @size}\n|" +
    (@board.map { |l| l.map{|e| " %#{digits}d " % e}.join }.join("|\n|")) +
    "|\n #{'-' * (digits+2) * @size}\n"
  end

  def solve
    half = (@size - 1) / 2 + 1
    half.times do |x|
      half.times do |y|
        @head = 1
        @tail = @size * @size
        cc = head(nil, @head, x, y)
        if cc
          tail(cc, @tail, *next_pos(x, y))
        end
        return self if @found
      end
    end
    self
  end

  private

  def valid?(x, y)
    x >= 0 && x < @size && y >= 0 && y < @size && !@board[x][y]
  end

  def nb_exit(x, y)
    MOVES.inject(0) { |m, (i, j)| valid?(x+i, y+j) ? m+1 : m }
  end

  def next_pos(x, y)
    MOVES.map { |i,j| [x+i, y+j] }.
      select  { |i,j| valid?(i, j) }.
      sort_by { |i,j| nb_exit(i, j)} [0]
  end

  def head(tail, nb, x, y=nil)
    @head = nb
    @found = true if @head >= @tail
    return if @found || !x
    @board[x][y] = nb
    tail = callcc { |cc|
      return cc if !tail
      tail.call cc
    }
    head(tail, nb+1, *next_pos(x, y))
  end

  def tail(head, nb, x, y=nil)
    @tail = nb
    @found = true if @head >= @tail
    return if @found || !x
    @board[x][y] = nb
    head = callcc { |cc|
      head.call cc
    }
    tail(head, nb-1, *next_pos(x, y))
  end

end

if __FILE__ == $0
  size = (ARGV[0] || 5).to_i
  puts PenAndPaperGame2.new(size).solve
end