Haskell и (волк, коза, капуста). Японская версия.
От: Sergey J. A. Беларусь  
Дата: 06.02.06 09:17
Оценка: 12 (2)
Hi all,

Пробегала тут недавно ссылочка на японскую головоломку — http://freeweb.siol.net/danej/riverIQGame.swf . Принцип аналогичен головоломке с перевозкой волка козы и капусты. И решил я написать решатель этой головоломки на Haskell-е. Для тренировки, так сказать. Написал и решил выложить. Вруг кому интересно, или кто решит указать мне на явные ляпы.
Только по голове сильно не бейте. Это моя первая программа на Haskell-е такого "громадного" объёма.

import Data.List
import Debug.Trace

-- Subject
data Subject = Mom | Girl | Boy | Pop | Cop | Crim
    deriving Show

instance Enum Subject where
    fromEnum Mom = 0
    fromEnum Girl = 1
    fromEnum Boy = 2
    fromEnum Pop = 3
    fromEnum Cop = 4
    fromEnum Crim = 5

instance Eq Subject where
    (==) s1 s2 = (fromEnum s1) == (fromEnum s2)

instance Ord Subject where
    (<=) s1 s2 = (<=) (fromEnum s1) (fromEnum s2)

--Raft
data Raft = Raft0 | Raft1 Subject | Raft2 Subject Subject

instance Enum Raft where
    fromEnum Raft0 = 0
    fromEnum (Raft1 s1) = fromEnum s1
    fromEnum (Raft2 s1 s2) = (fromEnum s1) * 1000 + (fromEnum s2)

instance Eq Raft where
    (==) r1 r2 = (fromEnum r1) == (fromEnum r2)

instance Ord Raft where
    (<=) r1 r2 = (fromEnum r1) <= (fromEnum r2)

instance Show Raft where
    show Raft0 = "{}"
    show (Raft1 r1) = "{" ++ show r1 ++ "}"
    show (Raft2 r1 r2) = "{" ++ show r1 ++ " & " ++ show r2 ++ "}"

-- direction
data Position = AtLeft | AtRight
    deriving Show

instance Enum Position where
    fromEnum AtLeft = 0
    fromEnum AtRight = 1

instance Eq Position where
    (==) p1 p2 = (fromEnum p1) == (fromEnum p2)

instance Ord Position where
    (<=) p1 p2 = (fromEnum p1) <= (fromEnum p2)
    
changePos AtLeft = AtRight
changePos AtRight = AtLeft

-- World
data World = World [Subject] Raft Position [Subject]
    
instance Eq World where
    (==) (World ls1 raft1 pos1 rs1) (World ls2 raft2 pos2 rs2) = 
            (sort ls1 == sort ls2) &&
            (raft1 == raft2) &&
            (pos1 == pos2) &&
            (sort rs1 == sort rs2)

instance Ord World where
    (<=) (World ls1 raft1 pos1 rs1) (World ls2 raft2 pos2 rs2) = 
            (sort ls1 <= sort ls2) || 
            ((sort ls1 == sort ls2) && (raft1 <= raft2)) ||
            ((sort ls1 == sort ls2) && (raft1 == raft2) && (pos1 <= pos2)) ||
            ((sort ls1 == sort ls2) && (raft1 == raft2) && (pos1 == pos2) && (sort rs1 <= sort rs2))

instance Show World where
    show (World ls Raft0 AtLeft rs) = show ls  ++ " "     ++ show Raft0 ++ "     " ++ show rs
    show (World ls raft AtLeft rs)  = show ls  ++ "     " ++ show raft  ++ " >>> " ++ show rs
    show (World ls Raft0 AtRight rs) = show ls ++ "     " ++ show Raft0 ++ " "     ++ show rs
    show (World ls raft AtRight rs)  = show ls ++ " <<< " ++ show raft  ++ "     " ++ show rs

validWorld  (World leftSide raft _ rightSide) = (not $ invalidWorld leftSide) && (not $ invalidWorld rightSide) 
            && (validRaft raft)
        where invalidWorld mans = ((Pop `elem` mans) && (not $ Mom `elem` mans) && (Girl `elem` mans)) 
                || ((not $ Pop `elem` mans) && (Mom `elem` mans) && (Boy `elem` mans))
                || ((Crim `elem` mans) && (not $ Cop `elem` mans) && (hereCivilian mans))

hereCivilian mans = (Mom `elem` mans) || (Pop `elem` mans) || (Girl `elem` mans) || (Boy `elem` mans)

outEnt   ent  = putStr $ show ent
outEnts  ents = putStr (foldl (\x y -> x ++ (show y) ++ "\n") "" ents) 

outEnts2 [] = do
                putStr ""
outEnts2 (h:t) = do
                outEnts2' h
                outEnts2 t

outEnts2' [] = do
                putStr "-----------------------\n"
outEnts2' (h:t) = do
                putStr ((show h) ++ "\n")
                outEnts2' t

traceIt [] = "^^^^^^^^^^^^^^^^^^^^^^^^\n"
traceIt (h:t) = (traceIt' $ h) ++ (traceIt t)

traceIt' [] = "-----------------------\n"
traceIt' (h:t) = ((show h) ++ "\n") ++ (traceIt' t)

--validate raft loading
validRaft Raft0 = True

validRaft (Raft1 Pop) = True
validRaft (Raft1 Mom) = True
validRaft (Raft1 Cop) = True
validRaft (Raft1 _) = False

validRaft (Raft2 Mom Boy) = False
validRaft (Raft2 Mom Crim) = False
validRaft (Raft2 Mom _) = True

validRaft (Raft2 Girl Mom) = True
validRaft (Raft2 Girl Cop) = True
validRaft (Raft2 Girl _) = False

validRaft (Raft2 Pop Girl) = False
validRaft (Raft2 Pop Crim) = False
validRaft (Raft2 Pop _) = True

validRaft (Raft2 Boy Mom) = True
validRaft (Raft2 Boy Cop) = True
validRaft (Raft2 Boy _) = False

validRaft (Raft2 Cop _) = True

validRaft (Raft2 Crim Cop) = True
validRaft (Raft2 Crim _) = False

-- return all possible rafts:
getAllRafts [] = []
getAllRafts (h:t) = [Raft1 h] ++ (map (\x -> (Raft2 h x)) t) ++ (getAllRafts t)
-- return only valid rafts.
getValidRafts l = filter validRaft (getAllRafts $ nub l)

-- remove first entrance of item from list
removeFirst _ [] = []
removeFirst e (h:t) | h==e = t
                    | otherwise = h : (removeFirst e t)

-- remove first entrance of 2 items from list
removeFirst2 e1 e2 list = removeFirst e2 (removeFirst e1 list)

-- load raft
loadRaft :: World -> Raft -> World
loadRaft (World ls Raft0 AtLeft rs) raft@(Raft1 r1)    = (World (removeFirst r1 ls) raft AtLeft rs)
loadRaft (World ls Raft0 AtLeft rs) raft@(Raft2 r1 r2) = (World (removeFirst2 r1 r2 ls) raft AtLeft rs)
loadRaft (World ls Raft0 AtRight rs) raft = (World ors raft AtRight ols)
        where (World ols _ _ ors) = loadRaft (World rs Raft0 AtLeft ls) raft

-- move raft to other side
moveRaft :: World -> World
moveRaft (World ls raft pos rs) = (World ls raft (changePos pos) rs)

-- unload raft
unloadRaft :: World -> World
unloadRaft (World ls (Raft1 r1   ) AtLeft  rs) = (World (ls ++ [r1    ]) Raft0 AtLeft  rs)
unloadRaft (World ls (Raft2 r1 r2) AtLeft  rs) = (World (ls ++ [r1, r2]) Raft0 AtLeft  rs)
unloadRaft (World ls raft          AtRight rs) = (World ors              Raft0 AtRight ols)
        where (World ols _ _ ors) = unloadRaft (World rs raft AtLeft ls)

allLoads :: World -> [World]
allLoads w@(World ls Raft0 AtLeft  rs) = map (\r -> loadRaft w r) (getValidRafts ls)
allLoads w@(World ls Raft0 AtRight rs) = map (\r -> loadRaft w r) (getValidRafts rs)

allValidLoads :: World -> [World]
allValidLoads w = filter (\x -> validWorld x) (allLoads w)

stepLoad :: [[World]] -> [[World]]
stepLoad []     = []
stepLoad (w:ws) = (stepLoadOne w) ++ (stepLoad ws)

stepLoadOne :: [World] -> [[World]]
stepLoadOne (w:log) = map (\neww -> (neww:log)) (nub $ sort $ allValidLoads w)

stepUnload :: [[World]] -> [[World]]
stepUnload []     = []
stepUnload (w:ws) = (stepUnloadOne w) : (stepUnload ws)

stepUnloadOne :: [World] -> [World]
stepUnloadOne l@(w:log) = (unloadRaft $ moveRaft w):l

step :: Int -> [[World]] -> [[World]]
step 0 x = map reverse x
step n x = step (n-1) (stepUnload $ stepLoad x)

isSolved :: World -> Bool
isSolved (World [] _ _ _) = True
isSolved _ = False

hasSolved :: [[World]] -> Bool
hasSolved [] = False
hasSolved (h:t) | isSolved (head h) = True
                | otherwise = hasSolved t

getSolved :: [[World]] -> [World]
getSolved [] = error "illegel getSolved"
getSolved (h:t) | isSolved (head h) = reverse h
                | otherwise = getSolved t

filterDupAndInvalid :: [[World]] -> [[World]]
filterDupAndInvalid x = nubBy (\(h1:_) (h2:_) -> h1 == h2) (filter (\(h:_) -> validWorld h) x)

-- get initial, return log
solve :: Int -> [[World]] -> [World]
solve 0 _ = error "Path not found !!!"
solve n l    | hasSolved l = getSolved l
            | otherwise = solve (n - 1) (filterDupAndInvalid $ stepUnload $ stepLoad l)

initial = World [Mom, Girl, Girl, Pop, Boy, Boy, Cop, Crim] Raft0 AtLeft []

main :: IO ()
main = outEnts $ solve 100 [[initial]]
I just ....
Re: Haskell и (волк, коза, капуста). Японская версия.
От: mihoshi Россия  
Дата: 06.02.06 09:29
Оценка:
Здравствуйте, Sergey J. A., Вы писали:


SJA> Пробегала тут недавно ссылочка на японскую головоломку — http://freeweb.siol.net/danej/riverIQGame.swf . Принцип аналогичен головоломке с перевозкой волка козы и капусты. И решил я написать решатель этой головоломки на Haskell-е. Для тренировки, так сказать. Написал и решил выложить. Вруг кому интересно, или кто решит указать мне на явные ляпы.

SJA>Только по голове сильно не бейте. Это моя первая программа на Haskell-е такого "громадного" объёма.

SJA>
SJA>import Data.List
SJA>import Debug.Trace

SJA>


ИМХО, слишком раздутый код...
Re[2]: Haskell и (волк, коза, капуста). Японская версия.
От: Sergey J. A. Беларусь  
Дата: 06.02.06 09:47
Оценка:
Здравствуйте, mihoshi, Вы писали:

M>ИМХО, слишком раздутый код...


Я тож думал, что получится короче. Но написал, и ничего значительного убрать не могу
Наверное много где можно было использовать стандартные ф-ии, но... пока маловато знаний этих самых стандартных ф-ий.
I just ....
Re: Haskell и (волк, коза, капуста). Японская версия.
От: Lazy Cjow Rhrr Россия lj://_lcr_
Дата: 06.02.06 10:02
Оценка:
Sergey J. A.,

Между прочим, работает тэг haskell
-- code goes here ...
instance Eq Subject where
    (==) s1 s2 = (fromEnum s1) == (fromEnum s2)
-- code goes here ...


Но это так, несущественное замечание.

По-существу, непонятно, что ожидает программа на входе и как получать решение.
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Re[2]: Haskell и (волк, коза, капуста). Японская версия.
От: Sergey J. A. Беларусь  
Дата: 06.02.06 10:16
Оценка: +1
Здравствуйте, Lazy Cjow Rhrr, Вы писали:

LCR>Между прочим, работает тэг haskell

Точно. Просто в янусе он ещё не работает, а на сайте оказывается уже всё есть
А я то всё гадал, зачем приписывают всякие теги типа ml и прочие...

LCR>По-существу, непонятно, что ожидает программа на входе и как получать решение.


Что-бы получить решение самой задачи нужно просто вычислить main. А начальное состояние задаётся в константе initial, как "мир" с перечислением субъектов на левом и правом берегу, положением и загрузкой плота:

initial = World [Mom, Girl, Girl, Pop, Boy, Boy, Cop, Crim] Raft0 AtLeft []


Над алгоритмом я сильно не думал (рвался в бой ). Он в принципе простой — берём массив состояний, находим для каждого состояния массив всех возможных состояний, всё склеиваем, удаляем лишние дубли. Так до момента, когда на левом берегу никого не останется. Или до n-ной итерации.

А что-бы вывести решение, храню "историю" для каждого состояния (все его предыдущие состояния).
I just ....
Re: Haskell и (волк, коза, капуста). Японская версия.
От: lomeo Россия http://lomeo.livejournal.com/
Дата: 06.02.06 12:34
Оценка: 6 (1)
Здравствуйте, Sergey J. A., Вы писали:

SJA>data Subject = Mom | Girl | Boy | Pop | Cop | Crim

SJA> deriving Show

SJA>instance Enum Subject where


Куча инстансов убирается дефолтной реализацией:
Например, для типа Subject:

data Subject = Mom | Girl | Boy | Pop | Cop | Crim
deriving (Eq, Enum, Ord, Show)

SJA>Только по голове сильно не бейте. Это моя первая программа на Haskell-е такого "громадного" объёма.


Заодно и код уменьшится

Насчет остального — я по диагонали смотрел, но

1. ты проверяешь валидность и мира и плота, по моему validRaft излишен (достаточно определить, что не только дети это достаточно).

2. \x -> (Raft2 h x) можно записать как Raft2 h. В твоем коде на этот счет мног можно сократить, но это больше понты.

3. removeFirst аналог функции delete (вообще, когда видишь у себя рекурсию — призадумайся, а не делал ли это кто до тебя, обычно уже или твоя функция есть или функция вычшего порядка, которая эту задачу может решить)

4. остальное лень было смотреть сорри
Re[2]: Haskell и (волк, коза, капуста). Японская версия.
От: Sergey J. A. Беларусь  
Дата: 06.02.06 13:15
Оценка:
Здравствуйте, lomeo, Вы писали:

L>Куча инстансов убирается дефолтной реализацией:

L>Например, для типа Subject:

L>data Subject = Mom | Girl | Boy | Pop | Cop | Crim

L> deriving (Eq, Enum, Ord, Show)

Ок. Надо над этим помедитировать, а то ещё в tutorial до deriving не дошёл.

L>1. ты проверяешь валидность и мира и плота, по моему validRaft излишен (достаточно определить, что не только дети это достаточно).

Ну, на плот ведь нельзя посадить Папу + Дочь. Тут просто надо унифицировать проверку берега и плота, и представить плот, как список (так же как и берег).

L>2. \x -> (Raft2 h x) можно записать как Raft2 h. В твоем коде на этот счет мног можно сократить, но это больше понты.

Я тож хотел так в паре мест сделать, но сдержался. Я бы потом сам ничего не понял

L>3. removeFirst аналог функции delete (вообще, когда видишь у себя рекурсию — призадумайся, а не делал ли это кто до тебя, обычно уже или твоя функция есть или функция вычшего порядка, которая эту задачу может решить)

Да. Я аналог этого removeFirst пытался найти, но проморгал.

L>4. остальное лень было смотреть сорри

Да я особо ни на что и не расчитывал.
Спасибо.
I just ....
Re: Haskell и (волк, коза, капуста). Японская версия.
От: Mikl Kurkov Россия  
Дата: 08.02.06 00:36
Оценка: 39 (4) :)
Здравствуйте, Sergey J. A., Вы писали:

SJA>Hi all,


SJA> Пробегала тут недавно ссылочка на японскую головоломку — http://freeweb.siol.net/danej/riverIQGame.swf . Принцип аналогичен головоломке с перевозкой волка козы и капусты. И решил я написать решатель этой головоломки на Haskell-е. Для тренировки, так сказать. Написал и решил выложить. Вруг кому интересно, или кто решит указать мне на явные ляпы.

SJA>Только по голове сильно не бейте. Это моя первая программа на Haskell-е такого "громадного" объёма.
SJA> ...
Я вот тоже решил написать для тренировки. На J.
Язык действительно интересный. Заставляет мозги по другому работать.
Из особенностей следующей программы хочу отметить что условия корректности состояния заданы декларативно глаголами в тацитной форме. not — это наречие (adverb) , поэтому пишется справа от глагола. Поиск производится встроенным оператором неподвижной точки ^:_ .
'`m g1 g2 f b1 b2 p c' =:(0&{)`(1&{)`(2&{)`(3&{)`(4&{)`(5&{)`(6&{)`(7&{)

and =: *.
or  =: +.
not =: -. @

cond1 =: m and (b1 or b2) and f not
cond2 =: f and (g1 or g2) and m not
cond3 =: c and (m or g1 or g2 or f or b1 or b2) and p not
cond  =: ( (cond1 or cond2 or cond3) not  )"1

raftcond =: ( cond and (m or f or p) )"1
raftmask =: (#~ 2&= @: (+/"1)) #: i.256

nextstates =: 3 : 0
  raft    =. (#~ raftcond) ~. raftmask *."1 y.
  from    =. y. -"1 raft
  to      =. raft +"1 -. y.
  from (and&cond # ]) to
)  

search1 =: 3 : 0
  l =. (#~ ($&1 0)@#) y. 
  r =. (#~ ($&0 1)@#) y. 
  if. (255 ~: {: r) and ((-: ~.) r) and ((-: ~.) l) 
   do. ( (,"_ 0) nextstates&.((8#2)&#:) @: {: ) y.
   else. y.
  end.        
)

search =: ~.@:,@:(<"1&search1&>"0) 
solutions =:  (#~ ((255&=@:{:) *. (0:= (2:|#))) @: >"0)  
out =: #&'MGGFBBPC' @: (- [: -. 1&|.) @: #:

~. out each solutions search ^:_ <255
Re[2]: Haskell и (волк, коза, капуста). Японская версия.
От: Sergey J. A. Беларусь  
Дата: 08.02.06 12:20
Оценка:
Здравствуйте, Mikl Kurkov, Вы писали:

MK>
    36 строк...
MK>


Мда... Моё решение пока занимает 148... Нужно сокращать
I just ....
Re[3]: Haskell и (волк, коза, капуста). Японская версия.
От: lomeo Россия http://lomeo.livejournal.com/
Дата: 08.02.06 13:31
Оценка:
Здравствуйте, Sergey J. A., Вы писали:

SJA>Мда... Моё решение пока занимает 148... Нужно сокращать


Понятным его сделать — само сократиться
Re: Haskell и (волк, коза, капуста). Японская версия.
От: Abulafia  
Дата: 09.02.06 00:09
Оценка:
On Mon, 06 Feb 2006 19:17:52 +1000, Sergey J. A. <12991@users.rsdn.ru>
wrote:

> Hi all,

>
> Пробегала тут недавно ссылочка на японскую головоломку —
> http://freeweb.siol.net/danej/riverIQGame.swf . Принцип аналогичен
> головоломке с перевозкой волка козы и капусты. И решил я написать
> решатель этой головоломки на Haskell-е. Для тренировки, так сказать.
> Написал и решил выложить. Вруг кому интересно, или кто решит указать мне
> на явные ляпы.
> Только по голове сильно не бейте. Это моя первая программа на Haskell-е
> такого "громадного" объёма.
>

А можно на оффтопичном языке (на Ruby)? Вроде, проще выглядит:

# b, b - boys
# g, g - girls
# o - outlaw
#
#
# M - Mother  ! Имена перевозчиков должны быть уникальны!
# F - Father
# P - Policeman
# N - None


class State

    # @left, @right -- массивы, в которых люди
    # @raft - положение плота: false -- слева, true -- справа
    # @next_left, @next_right -- следующие положения (для генерации  
следующего состояния)
    # @first, @second -- кому надо было переплыть
    
    attr_reader :left, :right, :raft, :next_left, :next_right, :first, :second
    
    
    def initialize(prevState, first, second)
        if prevState == nil
            # начальное состояние
            @left = ['b', 'b', 'g', 'g', 'o', 'M', 'F', 'P']
            @raft = false
        else        
            @prevState = prevState
            @left = prevState.next_left
            @right = prevState.next_right
            @raft = ! prevState.raft
            @first = first
            @second = second
        end
    end

        
    def move(first, second)
    
        if @prevState != nil
            return nil if ((@first == first) && (@second == second)) ||
                          ((@first == second) && (@first == second))
        end
    
        @next_left = Array.new(@left)
        @next_right = (@right == nil) ? [] : Array.new(@right)
    
        if @raft
            from = @next_right
            to = @next_left
        else
            from = @next_left
            to = @next_right
        end        
        
        from.delete_at(from.index(first))
        from.delete_at(from.index(second)) if second != '_'        
        to << first
        to << second if second != '_'
        
        # 1. Полицейский не может оставлять преступника с людьми одного.
        return nil if from.include?('o') && (from.length > 1) && (!  
from.include?('P'))
        return nil if to.include?('o') && (to.length > 1) && (! to.include?('P'))
        
        # 2. Папа не может оставлять сыновей одних с мамой, а мать - дочерей с  
папой.
        return nil if from.include?('M') && (! from.include?('F')) &&  
from.include?('b') # Мама с брошеными сыновьями
        return nil if to.include?('M') && (! to.include?('F')) &&  
to.include?('b') # Мама с брошеными сыновьями
        return nil if from.include?('F') && (! from.include?('M')) &&  
from.include?('g') # Папа с брошеными дочерьми
        return nil if to.include?('F') && (! to.include?('M')) &&  
to.include?('g') # Папа с брошеными дочерьми
        
        # Все правила соблюдены, делаем новое состояние
        return State.new(self, first, second)
    end
    
    
    def isEnd?
        return @left.empty? # && (@right.length == 8)
    end
    
    
    def printSolve
        if @prevState != nil
            @prevState.printSolve
        end
        print "(#{@first}, #{@second})  "
    end
    
end

@@MAX_DEPTH = 18

def turn(state, depth)

    if state.isEnd?
        state.printSolve
        print "\n"
        return        
    end
    
    # puts '.' * depth
    if depth >= @@MAX_DEPTH
        #state.printSolve
        #print "\n"
        return        
    end    
    
    from = (state.raft)?(state.right):(state.left)
    
    from.each { |first|
    
        # Первым должен быть взрослый
        next if (first != 'M') && (first != 'F') && (first != 'P')
        
        # Проверить возможность переплыва одному
        if newState = state.move(first, '_')
            turn(newState, depth + 1)
        end
        
        # Проверить возиожность переплыва с кем-л.    
        from.each { |second|        
            next if (first == second) # Должен быть другой участник, а не тот же  
самый
            
            if newState = state.move(first, second)
                turn(newState, depth + 1)
            end
        }

    }
end


initialState = State.new(nil, nil, nil)
turn(initialState, 1)


Выводит путь перевозки людей. Находит восемь решений.

--
WBR, Abulafia
Posted via RSDN NNTP Server 2.0
Re[2]: Haskell и (волк, коза, капуста). Японская версия.
От: Lazy Cjow Rhrr Россия lj://_lcr_
Дата: 09.02.06 13:04
Оценка: 2 (1)
Mikl Kurkov,

Я сделаю маленькое усовершенствование, можно?
'`m g1 g2 f b1 b2 p c' =: ". (, '`'&,)/ '('&, @ ,&'&{)' @ ":"0 @ i. 8

Это позволяет быстренько сгенерить глаголы для другого количества народу:
  (, '`'&,)/ '('&, @ ,&'&{)' @ ":"0 @ i. 10
(0&{)`(1&{)`(2&{)`(3&{)`(4&{)`(5&{)`(6&{)`(7&{)`(8&{)`(9&{)


PS: получил определённое удовольствие пока разбирался в твоей программе
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Re[3]: Haskell и (волк, коза, капуста). Японская версия.
От: Mikl Kurkov Россия  
Дата: 09.02.06 14:43
Оценка:
Здравствуйте, Lazy Cjow Rhrr, Вы писали:

LCR>Я сделаю маленькое усовершенствование, можно?

Что за вопрос. Не моно а нуно.

LCR>
LCR>'`m g1 g2 f b1 b2 p c' =: ". (, '`'&,)/ '('&, @ ,&'&{)' @ ":"0 @ i. 8
LCR>

LCR>Это позволяет быстренько сгенерить глаголы для другого количества народу:
LCR>
LCR>  (, '`'&,)/ '('&, @ ,&'&{)' @ ":"0 @ i. 10
LCR>(0&{)`(1&{)`(2&{)`(3&{)`(4&{)`(5&{)`(6&{)`(7&{)`(8&{)`(9&{)
LCR>

Хорошо. Но как говорится нет предела совершенству
Вот так еще интереснее получается:
vars =:  (([ , '=:'"_ , ] , '&{'"_)"1 ":"0 @: i. @: #) @: > @: ;:
   vars 'm g1 g2 f b1 b2 p c'
m =:0&{
g1=:1&{
g2=:2&{
f =:3&{
b1=:4&{
b2=:5&{
p =:6&{
c =:7&{

Соответственно использовать так:
". vars 'm g1 g2 f b1 b2 p c'
m
+-+-+-+
|0|&|{|
+-+-+-+

С помощью этого можно сделать универсальный решатель подобных головоломок.
Причем код почти готов для этого. Только убрать зависимости от количества участников и мест на плоту.
Условия можно передавать как текст, потом интерпретировать в процедуре.
Все очень наглядно получится.

LCR>PS: получил определённое удовольствие пока разбирался в твоей программе

Приятно слышать. Спасибо.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.