简体   繁体   English

列出给定 model 铁路上可能的火车路线

[英]List possible train routes on a given model railway

I want to calculate the available routes on a given model railway.我想计算给定 model 铁路上的可用路线。

Assumptions:假设:

  • All trains only start and stop on defined points which are called train stations.所有列车仅在称为火车站的定义点开始和停止。
  • Trains do not collide during their trip.火车在旅途中不会发生碰撞。 No need to worry about that.无需担心。
  • We don't have to think about the length of a train.我们不必考虑火车的长度。 We assume it is one locomotive which takes the space of an atom.我们假设它是一个占据原子空间的机车。
  • On one train station only one train can stop.在一个火车站,只有一列火车可以停靠。
  • A train can start and stop on the same train station.火车可以在同一个火车站开始和停止。

The start position and the end position of all trains are stored in a map.所有列车的开始 position 和结束 position 存储在 map 中。 All permutations are stored in a list.所有排列都存储在一个列表中。 Example:例子:

iex(1)> Trains.list_routes(["ICE"], ["Hamburg", "Frankfurt"])
[
  %{end: %{"ICE" => "Hamburg"}, start: %{"ICE" => "Hamburg"}},
  %{end: %{"ICE" => "Frankfurt"}, start: %{"ICE" => "Frankfurt"}},
  %{end: %{"ICE" => "Frankfurt"}, start: %{"ICE" => "Hamburg"}},
  %{end: %{"ICE" => "Hamburg"}, start: %{"ICE" => "Frankfurt"}}
]

A model railway could look like this (the red numbers indicate the train stations): model 铁路可能如下所示(红色数字表示火车站):

模型铁路的照片

For two trains on that model railway the function would be called this way:对于 model 铁路上的两列火车,function 将以这种方式调用:

Trains.list_routes([:red_train, :blue_train], ["1", "2", "3", "4", "5"])

Here's my current code:这是我当前的代码:

defmodule Trains do
  @moduledoc """
  Documentation for `Trains`.
  """

  @doc """
  Returns a list of all possible routes.

  ## Examples

      iex> Trains.list_routes([:red_train, :blue_train], ["Station 1", "Station 2"])
      [
        %{
          end: %{blue_train: "Station 2", red_train: "Station 1"},
          start: %{blue_train: "Station 2", red_train: "Station 1"}
        },
        %{
          end: %{blue_train: "Station 1", red_train: "Station 2"},
          start: %{blue_train: "Station 1", red_train: "Station 2"}
        },
        %{
          end: %{blue_train: "Station 1", red_train: "Station 2"},
          start: %{blue_train: "Station 2", red_train: "Station 1"}
        },
        %{
          end: %{blue_train: "Station 2", red_train: "Station 1"},
          start: %{blue_train: "Station 1", red_train: "Station 2"}
        }
      ]
  """
  def list_routes([], []) do
    []
  end

  def list_routes([train], [station]) do
    [
      %{start: %{train => station}, end: %{train => station}}
    ]
  end

  def list_routes([train], [station1, station2]) do
    [
      %{start: %{train => station1}, end: %{train => station1}},
      %{start: %{train => station2}, end: %{train => station2}},
      %{start: %{train => station1}, end: %{train => station2}},
      %{start: %{train => station2}, end: %{train => station1}}
    ]
  end

  def list_routes([train1, train2], [station1, station2]) do
    [
      %{
        start: %{train1 => station1, train2 => station2},
        end: %{train1 => station1, train2 => station2}
      },
      %{
        start: %{train1 => station2, train2 => station1},
        end: %{train1 => station2, train2 => station1}
      },
      %{
        start: %{train1 => station1, train2 => station2},
        end: %{train1 => station2, train2 => station1}
      },
      %{
        start: %{train1 => station2, train2 => station1},
        end: %{train1 => station1, train2 => station2}
      }
    ]
  end

  def list_routes(trains, train_stations) do
    # ???
  end
end

How can I loop through all combinations with list_routes(trains, train_stations) when the number of trains and the number of train_stations is bigger than 1?trains数量和train_stations数量大于 1 时,如何循环使用list_routes(trains, train_stations)的所有组合?

It is unclear why the same start and end station is allowed for the case of one train %{start: %{train => station1}, end: %{train => station1}} but not allowed for two trains, according to the code you've posted.不清楚为什么一列火车%{start: %{train => station1}, end: %{train => station1}}允许相同的起点和终点站,但不允许两列火车使用相同的起点和终点站,根据您发布的代码。

The good start would be somewhat along these lines:好的开始会有点沿着这些路线:

iex|1 ▶ {trains, stations} =
  {~w|red_train blue_train|a, ~w|1 2|}  
#⇒ {[:red_train, :blue_train], ["1", "2"]}
iex|2 ▶ (for t1 <- trains, t2<- trains, t1 != t2,
             s1 <- stations, s2 <- stations,
             do: Enum.sort([{t1, s1}, {t2, s2}])
        ) |> Enum.uniq()
#⇒ [
#   [blue_train: "1", red_train: "1"],
#   [blue_train: "2", red_train: "1"],
#   [blue_train: "1", red_train: "2"],
#   [blue_train: "2", red_train: "2"]
# ]

In any case,Kernel.SpecialForms.for/1 comprehension is your best friend here.无论如何,Kernel.SpecialForms.for/1理解是你最好的朋友。 Whether you need combinations and/or permutations, you might want to take a look at my Formulae library, specifically at Formulae.Combinators .无论您需要组合和/或排列,您可能想看看我的Formulae库,特别是在Formulae.Combinators

Here's a solution for the problem.这是该问题的解决方案。 It uses Formulae .它使用公式

mix.exs混合.exs

def deps do
  [{:formulae, "~> 0.8"}]
end

lib/trains.ex lib/trains.ex

def list_routes([], []) do
  []
end

def list_routes(trains, train_stations)
    when is_list(trains) and
            is_list(train_stations) and 
            length(train_stations) >= length(trains) do
  possible_states =
    Enum.map(Formulae.permutations(train_stations, length(trains)), &Enum.zip(trains, &1))

  for state_start <- possible_states, state_end <- possible_states do
    %{start: state_start, end: state_end}
  end
end

The result:结果:

iex(1)> Trains.list_routes([:red_train, :blue_train], ["Station 1", "Station 2"])
[
  %{
    end: [red_train: "Station 1", blue_train: "Station 2"],
    start: [red_train: "Station 1", blue_train: "Station 2"]
  },
  %{
    end: [red_train: "Station 2", blue_train: "Station 1"],
    start: [red_train: "Station 1", blue_train: "Station 2"]
  },
  %{
    end: [red_train: "Station 1", blue_train: "Station 2"],
    start: [red_train: "Station 2", blue_train: "Station 1"]
  },
  %{
    end: [red_train: "Station 2", blue_train: "Station 1"],
    start: [red_train: "Station 2", blue_train: "Station 1"]
  }
]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在值列表上映射任何给定的函数? - How do I map any given function over a list of values? 是否可以将数组转换为函数的参数列表? - Is it possible to turn an array into a list of parameters for a function? 是否可以在单词列表标记中转义空格? - Is it possible to escape a space in a word list sigil? Elixir Phoenix帮助关联模型列表 - Elixir Phoenix helper for associated model list 如何接收 erlang 或 elixir 中的可能值列表 - How to receive on a list of possible values in erlang or elixir 如何根据 elixir 中提供的条件对给定列表进行排序 - How to sort given list based on provided criteria in elixir Elixir - 在给定日期范围内过滤具有重叠日期的项目列表 - Elixir - filter list of items with overlapping dates with a given date range 等效的IO.inspect函数只返回字符串而不是打印给定列表,地图或关键字列表? - Equivalent of IO.inspect function that just returns string instead of printing given list, map or keyword list? Elixir:生成给定参数的 n 次出现的列表(类似于 Haskell 的复制) - Elixir: generate a list of `n` occurrences of a given argument (similar to Haskell's replicate) 如何选择给定模型的所有字段以及使用struct从关联中选择的字段,以避免过度获取 - How to select all fields for a given model along with selected fields from association using struct to avoid over-fetching
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM