ููุฏ ุฃุตุจุญ ุจุงููุนู ุชูููุฏูุง ุฌูุฏูุง - ูู ุดูุก ู ุซูุฑ ููุงูุชู ุงู ุธูุฑ ุนูู Haskell - ูุชูุฑุฑ ุนูู ุงูุฅูุณูุฑ.
ุงูุนูุงู ุฉ ุงูุฃููู ูุงูุช " ุญูุงูู 20 ุณุทุฑุงู ูุนุฏ ุงูููู ุงุช " ุ ูุงูุชู ุธูุฑุช ุนูู ุดูู ุญุฑู " ูุฒูู ุฉ C ุจุนุดุฑูู ุณุทุฑุงู ู ู ูุงุณูู: ูุชุงุจุฉ ู ุฑุญุงุถู ุงูุฎุงุต " ู ู0xd34df00d - ุตุงุฏูุช ุงูููู ุนุจุงุฑุฉ " ููู ุงูุฐุฆุจ ูุงูู ุงุนุฒ ูุงูู ูููู ุนุจุฑ ุงูููุฑ ู ุน ุงูุชุฃุซูุฑุงุช ูู ูุงุณูู " ู ููููุงุณูู ูู ูุฃูุถุง ูุง ูู ูู ุฃู ุชูุงูู .
ูุฐุง ุ ูุงุจู: ุงูููุฉ ุงูุบุงุดู ุฉ ุงูู ุชูุงุฒูุฉ ุบูุฑ ุงูู ุชุฒุงู ูุฉ ุงููุงู ูุฉ ุงูุจุทูุฆุฉ ู ูุงุจู ุงูุชุฃุซูุฑุงุช ุงูุฌุจุฑูุฉ.
ุจูุงู ุงูู ุดููุฉ (ุชู ูุณุฎู ุจุงู ุชูุงู ู ู ุงูู ูุงุญุธุฉ ุงูุฃุตููุฉ):
ูุงู ุงูููุงุญ ูู ููู ู ู ุงูุฃูุงู ุจุญุงุฌุฉ ุฅูู ููู ุฐุฆุจ ูู ุงุนุฒ ูู ูููู ุนุจุฑ ุงูููุฑ. ูู ุชูู ุงูููุงุญ ูุงุฑุจูุง ุ ุฅูู ุฌุงูุจ ุงูููุงุญ ููุณู ุ ูู ูู ุฃู ูุตูุญ ููู ุดูุก ูุงุญุฏ ููุท - ุฅู ุง ุฐุฆุจ ุฃู ู ุงุนุฒ ุฃู ู ูููู. ุฅุฐุง ุชุฑู ุงูููุงุญ ุงูุฐุฆุจ ูุงูู ุงุนุฒ ุฏูู ุฑูุงุจุฉ ุ ูุฃูู ุงูุฐุฆุจ ุงูู ุงุนุฒ ุ ุฅุฐุง ุชุฑู ุงูููุงุญ ุนูุฒุฉ ู ุน ู ูููู ุฏูู ุฑูุงุจุฉ ุ ูุฅู ุงูู ุงุนุฒ ุชุฃูู ุงูู ูููู.
: ยซ ยป, -, (+1 ). , โ , . , , . , , โ .
, .
defmodule WolfGoatCabbage.State do
@moduledoc """
.
(`true` โ , ), `ltr` โ , .
"""
defstruct banks: %{true => [], false => []}, ltr: true, history: []
end
defmodule WolfGoatCabbage.Subj do
@moduledoc """
, .
"""
defstruct [:me, :incompatible]
end
XIX , .
, .
@spec safe?(bank :: [%Subj{}]) :: boolean()
defp safe?(bank) do
subjs =
bank
|> Enum.map(& &1.me)
|> MapSet.new()
incompatibles =
bank
|> Enum.flat_map(& &1.incompatible)
|> MapSet.new()
MapSet.disjoint?(subjs, incompatibles)
end
, , , , , . .
()
, , (nil
ยซยป).
@spec move(%State{}, nil | %Subj{}) :: %State{} | false
@doc """
, ,
, .
"""
defp move(%State{ltr: ltr, banks: banks, history: history} = state, nil) do
with true <- not ltr, true <- safe?(banks[ltr]) do
%State{state | ltr: not ltr, history: [length(history) | history]}
end
end
@doc """
, , โ
.
, ,
( ) โ
. โ
, โ `false`.
"""
defp move(%State{banks: banks, ltr: ltr, history: history}, who) do
with true <- who in banks[ltr],
banks = %{ltr => banks[ltr] -- [who], not ltr => [who | banks[not ltr]]},
bank_state = MapSet.new(banks[true]),
true <- safe?(banks[ltr]),
true <- not Enum.member?(history, bank_state) do
%State{
banks: banks,
ltr: not ltr,
history: [bank_state | history]
}
end
end
()
, , : . .
@initial %State{
banks: %{true => @subjs, false => []},
history: [MapSet.new(@subjs)]
}
@spec go(%State{}) :: [MapSet.t()]
def go(state \\ @initial) do
case state.banks[true] do
[] -> # !
Enum.reverse(state.history)
_some ->
[nil | @subjs]
|> Task.async_stream(&move(state, &1))
|> Stream.map(&elem(&1, 1)) #
|> Stream.filter(& &1) #
|> Stream.flat_map(&go/1) #
end
end
Stream
, , , . , ?
: . main/0
.
ููุงู ูุงุฑู ุจุณูุท ูุงุญุฏ ููุง: ุณุชุนูุฏ ุงูุนุฏูุฏ ู
ู ุงูุญููู ููุงุฆู
ุฉ ุซุงุจุชุฉ ุจุณุจุจ Stream.flat_map/2
. ููู ูุฐุง ุฌูุฏ: ููุชูู ูู ุญู ุจู
ุฌู
ูุนุฉ ูุงุฑุบุฉ ุ ูุฐูู ูู
ูููุง ุจุณูููุฉ ุชูุณูู
ูุฐู ุงููุฑูุฉ ุงูู
ุณุทุญุฉ ุฅูู ูุทุน. ูู ููุฏ ุงูุฅุฎุฑุงุฌ ุงูุฌู
ูู (ูุงูุฐู ูู ุชูุฑูุจูุง ู
ุซู ุงูู
ูุทู) ูู ุฃุนุทููุง ููุง ุ ููุง ุฌููุฑ ููู
ุชุญู
ุณูู .
ููู ุฒุฑุงุนู ุณุนูุฏ!