I am a beginner and i have no idea what i am doing right now, need some help

So here is my code doing so far:

defmodule Shopping do

  def shop(list) do
	  products = %{orange: 5,
	             newspaper: 8,
	  	         apple: 2, 
	             pear: 9,
	             milk: 7}
		 
    shop(products, list, 0)
  end

  def shop(_products, [], total) do
	  total
  end
  
  def shop(products, [{product,qty} | list], total) do
	  {:ok, price} = Map.fetch(products, product)
	  count = shop(products, list, qty*price)
	  totalall = shop(products, list, total + qty*price)
	  IO.puts product ++ count ++ qty ++ totalall

  end
end

IO.puts Shopping.shop([{:orange,4},{:newspaper,1}])

and i try to get a result with

[{qty1, itemname1,price1,qty1*price1},{qty2, itemname2,price2,qty2*price2},{:total, pricetotal}]

like this:

iex(1) Shopping.shop([{:orange,4},{:newspaper,1}])
[{4, :orange, 5, 20},{1, :newspaper, 8, 8},{:total, 28}]

thanks for any help :sob:

Youā€™ll want to start by mastering the code fence - Elixir does not make good Markdown.

    ```
    type or paste code here
    ```

The button labeled ā€œ</>ā€ will also insert an empty set of code fences.

Another general thing to watch out for: IO.puts(things) returns :ok; putting it as the last line of a function means the function returns :ok too. For debugging, consider something like IO.inspect which passes through its input unchanged.

4 Likes

Hello and welcome,

I have reformatted your post to be more readableā€¦

Please consult this page for a better usability (Markdown)

2 Likes

If You have no idea about what You have been writting, then You might not understand solution as well. But if You have a slight idea, then itā€™s not that badā€¦ You could solve this recursively by using a list for total, and returning

[{q, product, p, p*q} | total]

Adding total could be made after building the list, or notā€¦ because itā€™s just a value You can easily calculate.

Itā€™s nice to learn and use recursion, but often You can use other tools. The Enum module for example.

You could solve your problem with Enum.map

3 Likes

Can you perhaps elaborate on what you get currently? We can then help you to debug and understand individual error messages and unexpected outcomes. This help you much better to understand than if we were just giving out a working solution.

4 Likes

Hello, it has been a week! I hope that you have resolved your issue, if not, this might be your answer.

defmodule Shop do
  def shop(product_list) do
    product_reference_list = %{orange: 5,
	                       newspaper: 8,
	  	                   apple: 2,
	                       pear: 9,
	                       milk: 7}

    init_accumulator = %{product_detail_list: [], total: 0}
    shop(product_reference_list, product_list, init_accumulator)
  end

  def shop(product_reference_list, [], accumulator) do
    accumulator

    product_detail_list = Map.get(accumulator, :product_detail_list)
    expected_array = Enum.map(product_detail_list, &(&1))
    expected_array ++ [Map.get(accumulator, :total)]
  end

  def shop(product_reference_list, [{product_name, product_quantity} | list], accumulator) do
    price_per_unit = Map.get(product_reference_list, product_name)
    product_total_price = price_per_unit * product_quantity

    product_detail = {product_quantity, product_name, price_per_unit, product_total_price}
    total_price = Map.get(accumulator, :total) + product_total_price

    accumulator = %{
      product_detail_list: Map.get(accumulator, :product_detail_list) ++ [product_detail],
      total: total_price
    }
    shop(product_reference_list, list, accumulator)
  end
end

In your interactive shell, you can test this code with the following commands:

product_list = [{:orange,4},{:newspaper,1}]
Shop.shop product_list

This is my screenshot.
Screenshot from 2020-03-09 18-47-20

1 Like

Hereā€™s my version:

defmodule Shopping do

  def shop(list) do
    priced_items = price_items(list)

    # Not optimal, but good enough for the exercise.

    total = Enum.reduce(priced_items, 0, fn {_, _, _, price}, acc ->
      acc + price
    end)

    priced_items ++ [total: total]		 
  end

  defp price_items(list) do
    # Let's call this prices.
    prices = %{orange: 5,
	             newspaper: 8,
	  	         apple: 2, 
	             pear: 9,
	             milk: 7}

    Enum.map(list, fn {product, qty} ->
      price = Map.fetch!(prices, product)
      {qty, product, price, price * qty}
    end)	
  end
end

IO.puts Shopping.shop([{:orange,4},{:newspaper,1}])

The rule of thumb is reach for the Enum mapping/reducing functions first, and try your hand at tail recursion only when you need to or as an exercise.

EDIT: didnā€™t catch the fact you wanted the price appended to the end. Updated my code.

EDIT 2, further simplification and optimisation, using the underrated Enum.map_reduce:

defmodule Shopping do
  def shop(list) do
    # Let's call this prices.
    prices = %{orange: 5,
	             newspaper: 8,
	  	         apple: 2, 
	             pear: 9,
	             milk: 7}

    {priced_items, total_price} = Enum.map_reduce(list, 0, fn {product, qty}, total ->
      price_per_unit = Map.fetch!(prices, product)
      price = price_per_unit * qty
      {{qty, product, price_per_unit, price}, total + price}
    end)	

    # Not optimal, but good enough for the exercise.
    priced_items ++ [total: total_price]	 
  end
end
3 Likes

update, here is how i do it for now

defmodule Shopping do


  @doc """
  Shop.

  ## Examples

      iex> Shopping.shop([{:orange,4},{:newspaper,1}])
      28

  """
  def shop(list) do
	  products = %{orange: 5,
	             newspaper: 8,
	  	         apple: 2, 
	             pear: 9,
	             milk: 7}
		 
    shop(products, list, 0)
  end

  def shop(_products, [], total) do
	  [{:total,total}]
  end
  def shop(products, [{product,qty} | list], total) do
	  {:ok, price} = Map.fetch(products, product)
	  [{qty,product,price,qty*price}| shop(products, list, total + qty*price)]
  end
end