它已经成为一种好习惯-在Haskell上出现的所有有趣的事情都在Elixir上重复出现。
第一个符号是“大约20行用于单词计数”,出现在“用二十行Haskell击败C:编写自己的wc ”中的小记号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。但这没关系:每个解决方案都以一个空集结尾,因此我们可以轻松地将此平板分成多个块。我不会在这里给出所有漂亮的输出代码(几乎与逻辑差不多),这是发烧友的要旨。

农业运输愉快!