使用列表在Elixir中进行映射。

huangapple go评论89阅读模式
英文:

Using list while mapping it in in Elixir

问题

我刚刚翻译的部分如下:

"I am new to Elixir programming, so i tried to solve some problems from Project Euler, but have a problem with 7th problem.

I solved the task but the code below is too slow.

Stream.iterate(2, &(&1 + 1))
|> Stream.filter(fn x -> Stream.find(2..x, fn y -> rem(x, y) == 0 end) == nil end)
|> Enum.take(10_001)

I want to read the current list while processing, because it's 10 times faster!

In imperative programming languages like Rust, I can do this:

    let mut list = vec![2];
    let mut i = 2;
    let mut is_prime: bool;

    while list.len() != n {
        i += 1;
        is_prime = true;

        for j in &list {
            if i % j == 0 {
                is_prime = false;
                break;
            }
        }

        if is_prime {
            list push(i);
        }
    }

When i tried to solve 10th problem, i wrote this code:

list = []

for i <- 2..(2_000_000 - 1) do
  if Enum.find(list, fn x -> rem(x, i) == 0 end) == nil do
    list = list ++ [i]
  end
end

Enum.sum(list) |> IO.puts()

But i got this message:

warning: variable "list" is unused (there is a variable with the same name in the context, use the pin operator (^) to match on it or prefix this variable with underscore if it is not meant to be used)

I expected the list to be updated but I can't even access it.

How can I solve these problems with my method in Elixir?"

英文:

I am new to Elixir programming, so i tried to solve some problems from Project Euler, but have a problem with 7th problem.

I solved the task but the code below is too slow.

Stream.iterate(2, &(&1 + 1))
|> Stream.filter(fn x -> Stream.find(2..x, fn y -> rem(x, y) == 0 end) == nil end)
|> Enum.take(10_001)

I want to read the current list while processing, because it's 10 times faster!

In imperative programming languages like Rust, I can do this:

    let mut list = vec![2];
    let mut i = 2;
    let mut is_prime: bool;

    while list.len() != n {
        i += 1;
        is_prime = true;

        for j in &list {
            if i % j == 0 {
                is_prime = false;
                break;
            }
        }

        if is_prime {
            list.push(i);
        }
    }

When i tried to solve 10th problem, i wrote this code:

list = []

for i <- 2..(2_000_000 - 1) do
  if Enum.find(list, fn x -> rem(x, i) == 0 end) == nil do
    list = list ++ [i]
  end
end

Enum.sum(list) |> IO.puts()

But i got this message:

warning: variable "list" is unused (there is a variable with the same name in the context, use the pin operator (^) to match on it or prefix this variable with underscore if it is not meant to be used)

I expected the list to be updated but I can't even access it.

How can I solve these problems with my method in Elixir?

答案1

得分: 0

以下应该能满足您的要求(但对于大型 n 值可能需要一些时间来完成,因为它是一个二次算法):

Enum.reduce(2..n, [], fn i, acc ->
  if Enum.any?(acc, fn x -> rem(i, x) == 0 end) do
    acc
  else
    [i | acc]
  end
end)
|> Enum.reverse()

重要的要点:

  • 使用 Enum.reduce/3 来方便地构建同时访问内容
  • 在累加器上使用前置(O(1)) 操作而不是追加(O(n)) 操作,然后在最后进行 反转
英文:

The following should do what you want (might take time to complete for big n values though since it's a quadratic algorithm):

Enum.reduce(2..n, [], fn i, acc -> 
  if Enum.any?(acc, fn x -> rem(i, x) == 0 end) do
    acc
  else
    [i | acc]
  end
end) 
|> Enum.reverse()

The important points:

  • Using Enum.reduce/3 which is convenient to build something while accessing it
  • Prepending (O(1)) instead of appending (O(n)) to the accumulator, and reversing at the end

huangapple
  • 本文由 发表于 2023年3月10日 01:16:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/75687946.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定