GolfScript, 82 ( 108 97 символів - 15 бонусів)
~),1/{{:F$0=),{F\+}/}%}@(*(0*\{1${1$\{\(@<},=},{1$\{\(@>},+(-!},:Y!{.,/+0}*;}/;Y{.-1=.@?)' '@)n}/
Оскільки я не знав жодної евристики, це рішення виконує вичерпний пошук у просторі рішення. Ви можете спробувати код в Інтернеті . Хоча реалізація є дуже ефективною, пошуковий простір зростає дуже швидко із збільшенням введення.
Приклади:
> 5 3
4 3
> 5 4
3 3
> 6 6
2 2
Як було сказано вище, реалізація не покладається на рекурсію, але відвідує кожен вузол пошукового простору лише один раз. Нижче ви знайдете примітку з кодовою версією коду, яка детальніше описує будівельні блоки.
Представлення однієї дошки розміром w * h задається переліком w- чисел у діапазоні від 0 до h . Кожне число дає кількість штук у відповідному стовпчику. Таким чином, допустима конфігурація - це список, де номери не збільшуються від початку до кінця (будь-яким переміщенням ви гарантуєте, що всі стовпці праворуч максимально вищі, ніж обрані).
~ # Evaluate the input (stack is now w h)
# BUILDING THE COMPLETE STATE SPACE
# Iteratively builds the states starting with 1xh board, then 2xh board, ...
),1/ # Generate the array [[0] [1] ... [h]] which is the space for 1xh
{ # This loop is now ran w-1 times and each run adds all states for the
# board with one additional column
{ # The {}/] block simply runs for each of the existing states
:F$0= # Take the smallest entry (which has to be the last one)
), # For the last column all values 0..x are possible
{F\+}/ # Append each of these values to the smaller state
}%
}@(*
# The order ensures that the less occupied boards are first in the list.
# Thus each game runs from the end of the list (where [h h ... h] is) to
# the start (where [0 0 ... 0] is located).
# RUN THROUGH THE SEARCH SPACE
# The search algorithm therefore starts with the empty board and works through all
# possible states by simply looping over this list. It builds a list of those states
# which are known as non-winning states, i.e. those states where a player should
# aim to end after the move
( # Skips the empty board (which is a winning configuration)
0*\ # and makes an empty list out of it (which will be the list of
# known non-winning states (initially empty))
{ # Loop over all possible states
1$ # Copy of the list of non-winning states
{ # Filter those which are not reachable from the current state,
# because at least one column has more pieces that the current
# board has
1$\{\(@<},=
},
{ # Filter those which are not reachable from the current state,
# because no valid move exists
1$\{\(@>},+ # Filter those columns which are different between start and
# end state
(-! # If those columns are all of same height it is possible to move
},
:Y # Assign the result (list of all non-winning states which are
# reachable from the current configuration within one move)
# to variable Y
!{ # If Y is non-empty this one is a winning move, otherwise
# add it to the list
.,/+
0 # Push dummy value
}*;
}/
; # Discard the list (interesting data was saved to variable Y)
# OUTPUT LOOP
# Since the states were ordered the last one was the starting state. The list of
# non-winning states were saved to variable Y each time, thus the winning moves
# from the initial configuration is contained in this variable.
Y{ # For each item in Y
.-1=.@?) # Get the index (1-based) of the first non-h value
' ' # Append a space
@) # Get the non-h value itself (plus one)
n # Append a newline
}/