# Run as: iex --dot-iex dp24a-fp2gy-megoldas.exs # Title: DP24a - 2. FP gyakorlat, 2024-09-10 Mix.install([ {:"Elixir.LastEr", path: "./", app: false, compile: false}, {:"Elixir.LastEx", path: "./", app: false, compile: false}, {:"Elixir.Nth", path: "./", app: false, compile: false} ]) # ── Rekurzív számítások ── # ### Legnagyobb közös osztó (greatest common divisor) euklideszi algoritmussal defmodule Gcd do @spec gcd(a :: integer(), b :: integer()) :: d :: integer() # a és b legnagyobb közös osztója d def gcd(a, 0), do: a def gcd(a, b) when a < b, do: gcd(b, a) def gcd(a, b), do: gcd(b, a - b) end (Gcd.gcd(96, 42) === 6) |> IO.inspect (Gcd.gcd(90, 45) === 45) |> IO.inspect # ### A Ludolph-féle szám, azaz $\pi$ közelítése a Leibniz-sorral defmodule Pi do @spec pi(i :: integer) :: pi :: float # A pi i-edik közelítő értéke pi def pi(i), do: 4 * pi_4(i*2+1, 1, :p, 0) defp pi_4(n, k, :p, pi) when k <= n, do: pi_4(n, k+2, :m, pi+(1/k)) defp pi_4(n, k, :m, pi) when k <= n, do: pi_4(n, k+2, :p, pi-(1/k)) defp pi_4(n, k, _, pi) when k > n, do: pi end (abs(Pi.pi(10000000) - :math.pi) < 1.0e-6) |> IO.inspect # ### Egész szám tetszőleges számrendszerbe konvertálása defmodule Dec2rad do @spec dec2rad(i :: integer, r :: integer) :: ds :: [integer] # Az i egész szám r alapú számrendszerbe konvertált, decimális számként # megadott számjegyeinek listája ds def dec2rad(i, r), do: dec2rad(i, r, []) defp dec2rad(0, _r, ds), do: ds defp dec2rad(i, r, ds), do: dec2rad((div i, r), r, [(rem i, r) | ds]) end (Dec2rad.dec2rad(13, 2) === [1, 1, 0, 1]) |> IO.inspect (Dec2rad.dec2rad(789, 17) === [2, 12, 7]) |> IO.inspect # ### Szülinapi gyertyák defmodule Candles do @type candles() :: [integer()] @spec candles(yrs::integer(), cndls::candles()) :: sols::[{rdx::integer(), solcndls::candles()}] # a sols lista solcndls listáinak azok a felhasznált gyertyák az elemei, # amelyekkel az adott rdx alapú számrendszerben a yrs szülinapszám kirakható # a cndls értékű gyertyák felhasználásával def candles(yrs, cndls), do: candles(yrs, cndls, yrs, []) def candles(_yrs, _cndls, 1, sols), do: sols def candles(yrs, cndls, rdx, sols) do dgts = Dec2rad.dec2rad(yrs, rdx) candles(dgts -- cndls, dgts, yrs, cndls, rdx, sols) end def candles([], dgts, yrs, cndls, rdx, sols), do: candles(yrs, cndls, rdx-1, [{rdx, dgts} | sols]) def candles([_|_], _dgts, yrs, cndls, rdx, sols), do: candles(yrs, cndls, rdx-1, sols) end (Candles.candles(76, [13,9,7,3]) == [{21, [3, 13]}, {23, [3, 7]}]) |> IO.inspect (Candles.candles(19, [9,7,1]) == [{10, [1, 9]}, {12, [1, 7]}]) |> IO.inspect # ── Összetettebb feladatok listák feldolgozására ── # ### Mátrix első oszlopában lévő elemek összegyűjtése defmodule FirstCol1 do @spec first_col(xss :: [[any()]]) :: zs :: [any()] def first_col([]), do: [] def first_col([[x | _xs] | xss]), do: [x | first_col(xss)] end xss = [[A, B, C], [:a, :b, :c], [1, 2, 3], [3.2, 2.1, 1.0]] (FirstCol1.first_col(xss) === [A, :a, 1, 3.2]) |> inspect() |> IO.puts() (FirstCol1.first_col([]) === []) |> inspect() |> IO.puts() defmodule FirstCol2 do @spec first_col(xss :: [[any()]]) :: zs :: [any()] def first_col(xss) do Enum.map(xss, &hd(&1)) end end xss = [[A, B, C], [:a, :b, :c], [1, 2, 3], [3.2, 2.1, 1.0]] (FirstCol2.first_col(xss) === [A, :a, 1, 3.2]) |> inspect() |> IO.puts() (FirstCol2.first_col([]) === []) |> inspect() |> IO.puts() defmodule FirstCol3 do @spec first_col(xss :: [[any()]]) :: zs :: [any()] def first_col(xss) do for [x | _xs] <- xss, do: x end end xss = [[A, B, C], [:a, :b, :c], [1, 2, 3], [3.2, 2.1, 1.0]] (FirstCol3.first_col(xss) === [A, :a, 1, 3.2]) |> inspect() |> IO.puts() (FirstCol3.first_col([]) === []) |> inspect() |> IO.puts() # ### Listák első elemeinek összegyűjtése defmodule FirstElem1 do @spec first_elem(xss :: [[any()]]) :: zs :: [any()] def first_elem([]), do: [] def first_elem([[] | xss]), do: first_elem(xss) def first_elem([[x | _xs] | xss]), do: [x | first_elem(xss)] end xss = [[A, B, C], [:a, :b, :c], [1, 2, 3], [3.2, 2.1, 1.0]] (FirstElem1.first_elem(xss) === [A, :a, 1, 3.2]) |> inspect() |> IO.puts() xss = [[A, B], [:a, :b, :c, :d], [1], [], [3.2, 2.1, 1.0]] (FirstElem1.first_elem(xss) === [A, :a, 1, 3.2]) |> inspect() |> IO.puts() (FirstElem1.first_elem([]) === []) |> inspect() |> IO.puts() defmodule FirstElem2 do @spec first_elem(xss :: [[any()]]) :: zs :: [any()] def first_elem(xss) do xss |> Enum.filter(&(&1 != [])) |> Enum.map(&hd(&1)) end end xss = [[A, B, C], [:a, :b, :c], [1, 2, 3], [3.2, 2.1, 1.0]] (FirstElem2.first_elem(xss) === [A, :a, 1, 3.2]) |> inspect() |> IO.puts() xss = [[A, B], [:a, :b, :c, :d], [1], [], [3.2, 2.1, 1.0]] (FirstElem2.first_elem(xss) === [A, :a, 1, 3.2]) |> inspect() |> IO.puts() (FirstElem2.first_elem([]) === []) |> inspect() |> IO.puts() defmodule FirstElem3 do @spec first_elem(xss :: [[any()]]) :: zs :: [any()] def first_elem(xss) do for [x | _xs] <- xss, do: x end end xss = [[A, B, C], [:a, :b, :c], [1, 2, 3], [3.2, 2.1, 1.0]] (FirstElem3.first_elem(xss) === [A, :a, 1, 3.2]) |> inspect() |> IO.puts() xss = [[A, B], [:a, :b, :c, :d], [1], [], [3.2, 2.1, 1.0]] (FirstElem3.first_elem(xss) === [A, :a, 1, 3.2]) |> inspect() |> IO.puts() (FirstElem3.first_elem([]) === []) |> inspect() |> IO.puts() # Módosítsa úgy a megoldását, hogy üres lista esetén a lista feje helyett a `nil` atomot rakja be az eredménylistába. defmodule FirstElem4 do @spec first_elem(xss :: [[any()]]) :: zs :: [any()] def first_elem([]), do: [] def first_elem([[] | xss]), do: [nil | first_elem(xss)] def first_elem([[x | _xs] | xss]), do: [x | first_elem(xss)] end xss = [[A, B], [:a, :b, :c, :d], [1], [], [3.2, 2.1, 1.0]] (FirstElem4.first_elem(xss) === [A, :a, 1, nil, 3.2]) |> inspect() |> IO.puts() defmodule FirstElem5 do @spec first_elem(xss :: [[any()]]) :: zs :: [any()] def first_elem(xss) do xss |> Enum.map(fn [] -> nil [x | _xs] -> x end) end end xss = [[A, B], [:a, :b, :c, :d], [1], [], [3.2, 2.1, 1.0]] (FirstElem5.first_elem(xss) === [A, :a, 1, nil, 3.2]) |> inspect() |> IO.puts() defmodule FirstElem6 do @spec first_elem(xss :: [[any()]]) :: zs :: [any()] def first_elem(xss) do for xs <- xss, do: (case xs do [] -> nil [x | _xs] -> x end) end end xss = [[A, B], [:a, :b, :c, :d], [1], [], [3.2, 2.1, 1.0]] (FirstElem6.first_elem(xss) === [A, :a, 1, nil, 3.2]) |> inspect() |> IO.puts() # ### Elfajult mátrix első oszlopának transzponálása defmodule FirstColTranspose1 do @spec first_col_transpose(xss :: [[any()]]) :: zss :: [[any()]] def first_col_transpose(xss) do [ for( xs <- xss, do: case xs do [] -> nil [x | _xs] -> x end ) | for( xs <- xss, do: case xs do [] -> [] [_x | xs] -> xs end ) ] end end xss = [[A, B, C], [:a, :b, :c], [1, 2, 3], [3.2, 2.1, 1.0]] zss = [[A, :a, 1, 3.2], [B, C], [:b, :c], [2, 3], [2.1, 1.0]] (FirstColTranspose1.first_col_transpose(xss) === zss) |> inspect() |> IO.puts() xss = [[A, B], [:a, :b, :c, :d], [1], [3.2, 2.1, 1.0]] zss = [[A, :a, 1, 3.2], [B], [:b, :c, :d], [], [2.1, 1.0]] (FirstColTranspose1.first_col_transpose(xss) === zss) |> inspect() |> IO.puts() (FirstColTranspose1.first_col_transpose([]) === [[]]) |> inspect() |> IO.puts() xss = [[A, B], [:a, :b, :c, :d], [1], [], [3.2, 2.1, 1.0]] zss = [[A, :a, 1, nil, 3.2], [B], [:b, :c, :d], [], [], [2.1, 1.0]] (FirstColTranspose1.first_col_transpose(xss) === zss) |> inspect() |> IO.puts() defmodule FirstColTranspose2 do @spec first_col_transpose(xss :: [[any()]]) :: zss :: [[any()]] def first_col_transpose(xss) do {zs, zss} = xss |> Enum.map(fn [x | xs] -> {x, xs} [] -> {nil, []} end) |> Enum.unzip() [zs | zss] end end xss = [[A, B, C], [:a, :b, :c], [1, 2, 3], [3.2, 2.1, 1.0]] zss = [[A, :a, 1, 3.2], [B, C], [:b, :c], [2, 3], [2.1, 1.0]] (FirstColTranspose2.first_col_transpose(xss) === zss) |> inspect() |> IO.puts() xss = [[A, B], [:a, :b, :c, :d], [1], [3.2, 2.1, 1.0]] zss = [[A, :a, 1, 3.2], [B], [:b, :c, :d], [], [2.1, 1.0]] (FirstColTranspose2.first_col_transpose(xss) === zss) |> inspect() |> IO.puts() (FirstColTranspose2.first_col_transpose([]) === [[]]) |> inspect() |> IO.puts() xss = [[A, B], [:a, :b, :c, :d], [1], [], [3.2, 2.1, 1.0]] zss = [[A, :a, 1, nil, 3.2], [B], [:b, :c, :d], [], [], [2.1, 1.0]] (FirstColTranspose2.first_col_transpose(xss) === zss) |> inspect() |> IO.puts() defmodule FirstColTranspose3 do @spec first_col_transpose(xss :: [[any()]]) :: zss :: [[any()]] def first_col_transpose([]), do: [[]] def first_col_transpose([[x | xs] | xss]) do [ys | yss] = first_col_transpose(xss) [[x | ys] | [xs | yss]] end def first_col_transpose([[] | xss]) do [ys | yss] = first_col_transpose(xss) [[nil | ys] | [[] | yss]] end end xss = [[A, B, C], [:a, :b, :c], [1, 2, 3], [3.2, 2.1, 1.0]] zss = [[A, :a, 1, 3.2], [B, C], [:b, :c], [2, 3], [2.1, 1.0]] (FirstColTranspose3.first_col_transpose(xss) === zss) |> inspect() |> IO.puts() xss = [[A, B], [:a, :b, :c, :d], [1], [3.2, 2.1, 1.0]] zss = [[A, :a, 1, 3.2], [B], [:b, :c, :d], [], [2.1, 1.0]] (FirstColTranspose3.first_col_transpose(xss) === zss) |> inspect() |> IO.puts() (FirstColTranspose3.first_col_transpose([]) === [[]]) |> inspect() |> IO.puts() xss = [[A, B], [:a, :b, :c, :d], [1], [], [3.2, 2.1, 1.0]] zss = [[A, :a, 1, nil, 3.2], [B], [:b, :c, :d], [], [], [2.1, 1.0]] (FirstColTranspose3.first_col_transpose(xss) === zss) |> inspect() |> IO.puts() # A következő feladatokban az előző gyakorlaton megírt függvényeket kell alkalmaznia (`LastEr.last/1`, `LastEx.last/1`), `Nth.nth/2`. # ### Listák utolsó elemeinek listája defmodule LastOfListsEr do @spec last_of_lists(xss :: [[any()]]) :: zs :: [any()] # xss utolsó elemeinek listája zs def last_of_lists([]), do: [] def last_of_lists([xs | xss]) do case LastEr.last(xs) do {:ok, x} -> [x | last_of_lists(xss)] :error -> last_of_lists(xss) end end end IO.puts(LastOfListsEr.last_of_lists([]) == []) IO.puts(LastOfListsEr.last_of_lists([[]]) == []) IO.puts(LastOfListsEr.last_of_lists([[], ~c""]) == []) IO.puts(LastOfListsEr.last_of_lists([~c"apple", ~c"peach", ~c"", ~c"orange"]) == ~c"ehe") # Írja meg a függvény egy változatát az előző gyakorlaton szintén megírt `LastEx.last/1` függvény alkalmazásával. defmodule LastOfListsEx do @spec last_of_lists(xss :: [[any()]]) :: zs :: [any()] # xss utolsó elemeinek listája zs def last_of_lists([]), do: [] def last_of_lists([xs | xss]) do case LastEx.last(xs) do nil -> last_of_lists(xss) x -> [x | last_of_lists(xss)] end end end IO.puts(LastOfListsEx.last_of_lists([]) == []) IO.puts(LastOfListsEx.last_of_lists([[]]) == []) IO.puts(LastOfListsEx.last_of_lists([[], ~c""]) == []) css = [~c"now", ~c"bye", ~c"", ~c"hell", ~c"cell", ~c""] (LastOfListsEx.last_of_lists(css) == ~c"well") |> IO.puts() # ### Listák utolsó előtti elemeinek listája defmodule LastButOnesEx do @spec last_but_ones(xss :: [[any()]]) :: zs :: [any()] # xss utolsó előtti elemeinek listája zs def last_but_ones([]), do: [] def last_but_ones([xs | xss]) do case Nth.nth(xs, length(xs) - 2) do nil -> last_but_ones(xss) x -> [x | last_but_ones(xss)] end end end IO.puts(LastButOnesEx.last_but_ones([]) == []) IO.puts(LastButOnesEx.last_but_ones([[]]) == []) IO.puts(LastButOnesEx.last_but_ones([[], ~c""]) == []) IO.puts(LastButOnesEx.last_but_ones([~c"bye", ~c"tiles", ~c"", ~c"list"]) == ~c"yes")