tommy

tommy

I created a small scripts that takes a lottery number of length x and loops until it finds a match. I created it just for learning purposes and out of curiosity of how many loops are needed to find a match.

At the moment it prints the number of loops to the terminal but I would prefer if it only printed every 5000 or so tries.

I put an if expression that checks the see if loop_num / 5000 ends in 0, in the cond for each non match but I get the following error:

"elixir elixirPlay.exs
** (SyntaxError) elixirPlay.exs:83: unexpected token: ). The “do” at line 77 is missing terminator “end”

HINT: it looks like the "do" on line 1 does not have a matching "end"

(elixir) lib/code.ex:813: Code.require_file/2

"

If I comment out the if it works again. Are if expressions allowed in conds? What’s the solution?

Any other other critiques on the code?

defmodule Play do

def random_numbered_balls num do
    (for _x <- 1..num, do: Enum.random 1..49) |> List.to_tuple
end


def loto(true), do: IO.puts "We have a match!"

def loto(num_of_balls), do: loto(random_numbered_balls(num_of_balls), num_of_balls, 0) 

def loto(static_balls_list, num_of_balls, loop_num) do
    static_balls = static_balls_list
    changing_balls = random_numbered_balls(num_of_balls)
    cond do
        (static_balls == changing_balls) ->
            IO.inspect static_balls 
            IO.inspect changing_balls
            loto(true) 
        (static_balls != changing_balls) ->
            #if (String.ends_with?(to_string(loop_num / 5000)), "0")), do: IO.puts "#{loop_num} tries"
            IO.puts "#{loop_num} tries" #(temp) would prefer to print only ever 5000 tries but can't get the above to work
            loop_num = (loop_num + 1)
            loto(static_balls, num_of_balls, loop_num)
    end
end

end #module end


Play.loto(x)

Showing Posts 1 to 10

al2o3cr

al2o3cr

if (String.ends_with?(to_string(loop_num / 5000)), "0"))

This has too many ).

It should also be spelled if (loop_num % 5000 == 0), partly because that’s much more efficient than converting to string and checking the last character but mostly because / in Elixir does not mean integer division:

4214 / 5000
# evaluates to
0.8428

Other general notes:

static_balls = static_balls_list

What’s the intent of this line?

(static_balls != changing_balls) ->

Parentheses are not required here.

loop_num = (loop_num + 1)

And they’re DEFINITELY not required here

I highly recommend learning about and using mix format - it helps remember all the “where do the parens go” rules.

tommy

tommy OP

Thank you for the help.

Well spotted, “static_balls = static_balls_list” is redundant. It’s was left over from when the code was different. I have now deleted it, and replaced all static_balls with static_balls_list.

I edited the if to (loop_num % 5000 == 0) and get the following error:

(SyntaxError) elixirPlay.exs:83: syntax error before: ‘)’
(elixir) lib/code.ex:813: Code.require_file/2

The full line is: if (loop_num % 5000 == 0), do: IO.puts “#{loop_num} tries”

Thanks for the other pointers and I’ll check out https://hexdocs.pm/mix/Mix.Tasks.Format.html#content

tommy

tommy OP

I now have the if expression working with ((rem loop_num, 5000) == 0)
Edit: or (rem loop_num, 5000) == 0
Maybe I should have been a lisper!

kokolegorille

kokolegorille

You can always switch to LFE :slight_smile:

tommy

tommy OP

You can always switch to LFE :slight_smile:

Oh wow, never head of that!

tommy

tommy OP

Finished and tidied up.

def random_numbered_balls num do
    (for _x <- 1..num, do: Enum.random 1..49) |> List.to_tuple
end


def lotto(true), do: {:match_found}
def lotto(num_of_balls), do: lotto(random_numbered_balls(num_of_balls), num_of_balls, 0) 
def lotto(static_balls_list, num_of_balls, loop_num) do
    changing_balls = random_numbered_balls num_of_balls
    cond do
        (static_balls_list == changing_balls) ->
            IO.inspect static_balls_list
            IO.inspect changing_balls
            IO.puts "We have a match. It took #{loop_num} tries in total."
            lotto(true) 
        (static_balls_list != changing_balls) ->
            if (rem loop_num, 100000) == 0, do: IO.puts "#{loop_num} tries"
            loop_num = loop_num + 1
            lotto(static_balls_list, num_of_balls, loop_num)
    end
end
end #module end

Play.lotto(3)
Matsa59

Matsa59

Hello,

def lotto(static_balls_list, num_of_balls, loop_num) do
    cond do
        (static_balls_list == changing_balls) ->

        (static_balls_list != changing_balls) ->
            # if your code goes the condition before is always true
    end
end

you can simply do

def lotto(static_balls_list, num_of_balls, loop_num) do
    if static_balls_list == changing_balls do
    else
    end
end

also you return loto(true you can direclty return the result {:match_found}

You have 3 functions signatures for loto

def lotto(true), do: {:match_found}
def lotto(num_of_balls), do: lotto(random_numbered_balls(num_of_balls), num_of_balls, 0) 
def lotto(static_balls_list, num_of_balls, loop_num) do

that describres 3 differents behaviour.

I rewrite your code as I probably code it (just sharing way of think not judging)

defmodule Loto do
  def shuffle(num) do
    # Use a List is better than custom Tuple length
    for _x <- 1..num, do: :rand.uniform(49)
  end

  # start loto
  def start(num_of_balls) do
    win?(
      shuffle(num_of_balls),
      shuffle(num_of_balls)
    )
  end
  
  # This line just set the default value for the 3th parameter
  # and is know as a function signature that do nothing more ;)
  def win?(list_of_balls, other_list_of_balls, loop_num \\ 1)

  # if we provide 1st et 2nd is the same value basically you win
  def win?(balls_list, balls_list, loop_num) do
    IO.puts("We have a match. It took #{loop_num} tries in total.")
    :match_found
  end

  # otherwise try again
  def win?(_, balls_list, loop_num) do
    if rem(loop_num, 100_000) == 0, do: IO.puts("#{loop_num} tries")

    balls_list
    |> Enum.count()
    |> shuffle()
    |> win?(balls_list, loop_num + 1)
  end
end


Loto.start(1)

I think win?/3 could be improve not my best piece of code.

Also start / win? will always return :match_found so not a usefull return.

Hope it help :wink:

tommy

tommy OP

Thank you, very interesting. I’ll reread your message tomorrow, run it and reply :).

tommy

tommy OP

Have just been playing with your code solution. I find it clean and elegant. On the one hand I find it depressing as I was really happy with what I wrote but on the other, I feel excited as I can see how clean code can be. With my dyslexia and ADD, I find it difficult to read/write and follow code. From your code I can see that it can be broken up into small sub problems that are easy to follow.

I’m going let some forgetting set in, then rewrite it in a week or so with this new mind set. I’m really enjoying this journey.

Just one question: What is a List better than a Tuple ? I started with a List but because I kept printing Chars from the code points I switched to Tuples. I find choosing the best collection to use still a little confusing.

kokolegorille

kokolegorille

A tuple has a fixed size while list can grow.

Where Next? Top

Trending in Questions Top

RSP87
I’m working on a project that simulates the bumbl example in the programming phoenix book. It acts almost like an email client. We have a...
New
nseaSeb
Hello, I know there is an approach for handling lists that allows for optimized traversal, but I can’t recall the specific method (somet...
New
kpanic
Hi everyone, I am toying with the idea of building a “match maker” for giving personal help to people that wants to start coding. I sta...
New
brecabral
Documentation While reading the Scoped Routes section, I noticed that the documentation currently refers to a problem without explainin...
New
velrest
So my question is quite simple and i have found no conclusive answer on forum, google or AI. Should we use :erlang.float for Integer to ...
New
asweet-confluent
I recently noticed that Elixir’s Logger defaults its primary log level to :debug when no :logger, :level application configuration is pre...
New
samoloth
Hi, I’ve just set up an application with ash_authentication. There is only magic link strategy for now, so there is no confirmation add o...
New

Other Trending Topics Top

JesseHerrick
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
mhanberg
Hi everyone! The first release candidate for the Expert language server project is now available! We’ve published a press release detai...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Dmk
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New

Latest on Elixir Forum

Elixir Forum

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews