defmodule Dp.Fun do # @author "hanak@emt.bme.hu" # @date "$LastChangedDate: 2024-10-07 07:55:33 +0200 (Mon, 07 Oct 2024) $$" # import Integer, only: [is_even: 1] # require Integer # stir és stir_2 nem csinál semmi értelmeset, csak illusztrálja # a klózok definiálását és a szekvenciális kifejezés használatát # egy névtelen és egy neves függvényben stir = fn {a, b} when a < b -> {b, a} {a, b} when rem(a,b) === 0 -> d = div(a, b); {b, d} x -> x end @spec stir_2(x::{integer(), integer()} | any()) :: r::({integer(), integer()} | any()) # r egy megkavart pár, ha x pár, egyébként x def stir_2({a, b}) when a < b, do: {b, a} def stir_2({a, b}) when rem(a,b) === 0, do: (d = div(a,b); {b, d}) def stir_2(x), do: x @spec sumsq(x::number(), y::number()) :: n::number() # x és y négyzetösszege n (x^2 + y^2 = n) def sumsq(x, y), do: ( sq = fn x -> x*x end; sq.(x) + sq.(y) ) @spec sumtr(f::((number())-> number()), x::number(), y::number()) :: n::number() # x és y f-vel transzformált értékének összege n def sumtr(f, x, y), do: f.(x) + f.(y) @spec sumx2y2z(x::number(), y::number(), z::number()) :: n::number() # x^2 + y^2 + z = n def sumx2y2z(x, y, z), do: ( sq = fn x -> x*x end; sq.(x) + sq.(y) + z ) @spec picked(xs::[any()], d::integer()) :: rs::[integer()] # def picked(xs, d), do: Enum.sort((picked xs, d, d), &>/2) @spec picked(xs::[any()], d::integer(), i::integer()) :: rs::[integer()] # defp picked([x|xs], d, i) when (is_integer x) and (rem x,d) === 0 do [ x * i | picked(xs, d, i+1) ] end defp picked([_x|xs], d, i), do: picked(xs, d, i) defp picked([], _d, _i), do: [] @spec filt(xs::[any()], d::integer()) :: rs::[integer()] # xs d-vel osztható egészszám-elemeinek listája rs defp filt([x|xs], d) when (is_integer x) and (rem x,d) === 0 do [ x | filt(xs, d) ] end defp filt([_x|xs], d), do: filt(xs, d) defp filt([], _d), do: [] @spec mult(xs::[number()], i::number()) :: rs::[number()] # xs elemeit a minden rekurzív lépésben eggyel megnövelt #i-vel megszorozva kapjuk rs-t defp mult([x|xs], i), do: [x * i | mult(xs, i+1)] defp mult([], _i), do: [] @spec picked_2(xs::[any()], d::integer()) :: rs::[integer()] # def picked_2(xs, d), do: Enum.sort(mult(filt(xs, d), d), &>/2) @spec picked_3(xs::[any()], d::integer()) :: rs::[integer()] # defp picked_3(xs, d) do fs = filt(xs, d) ms = mult(fs, d) Enum.sort(ms, &>/2) end @spec picked_4a(xs::[any()], d::integer()) :: rs::[integer()] # def picked_4a(xs, d), do: xs |> filt(d) |> mult(d) |> Enum.sort(&>/2) @spec picked_4(xs::[any()], d::integer()) :: rs::[integer()] # defp picked_4(xs, d) do xs |> filt(d) |> mult(d) |> Enum.sort(&>/2) end @spec filt_2(xs::[any()], p?::((any()) -> boolean())) :: rs::[any()] # xs p?-t kielégítő elemeinek listája rs def filt_2([x|xs], p?), do: (if p?.(x), do: [ x | filt_2(xs, p?) ], else: filt_2(xs, p?)) def filt_2([], _p?), do: [] @spec oper(xs::[any()], {f::((any(), any())->any()), i::any()}) :: rs::[any()] # f-et az xs elemeire és a minden rekurzív lépésben eggyel megnövelt # i-re alkalmazva kapjuk rs-t defp oper([x|xs], {f,i}), do: [ f.(x,i) | oper(xs, {f,i+1}) ] defp oper([], _fi), do: [] @spec picked_5(xs::[any()], d::integer()) :: rs::[integer()] # defp picked_5(xs, d) do p? = &(is_integer &1) and (rem &1, d) === 0 f = &(&1 * &2) xs |> filt_2(p?) |> oper({f, d}) |> Enum.sort(&>/2) end @spec map(xs::[any()], f::((any()) -> any())) :: rs::[any()] # xs elemeinek f-fel transzformált listája rs def map([x|xs], f), do: [ f.(x) | map(xs, f) ] def map([], _f), do: [] @spec filter(xs::[any()], p?::((any()) -> boolean())) :: rs::[any()] # xs p?-t kielégítő elemeinek listája rs def filter([x|xs], p?), do: (if p?.(x), do: [ x | filter(xs, p?) ], else: filter(xs, p?)) def filter([], _p?), do: [] @spec sumr(xs::[integer()], acc::integer()) :: r::integer() # az xs elemeinek és az acc-nek az összege r def sumr([x|xs], acc), do: (&+/2).(x, sumr(xs, acc)) def sumr([], acc), do: acc @spec suml(xs::[integer()], acc::integer()) :: r::integer() # az xs elemeinek és az acc-nek az összege r def suml([x|xs], acc), do: suml(xs, (&+/2).(x, acc)) def suml([], acc), do: acc @spec foldr(xs::[any()], acc::any(), f::((x::any(), y::any()) -> r::any())) :: r::any() # Az xs listában jobbról balra haladva az xs elemeiből és az acc-ból a # kétoperandusú f-fel képzett érték r def foldr([x|xs], acc, fun), do: fun.(x, foldr(xs, acc, fun)) def foldr([], acc, _fun), do: acc @spec foldl(xs::[any()], acc::any(), f::((x::any(), y::any()) -> r::any())) :: r::any() # Az xs listában balról jobbra haladva az xs elemeiből és az acc-ból a # kétoperandusú f-fel képzett érték r def foldl([x|xs], acc, fun), do: foldl(xs, fun.(x, acc), fun) def foldl([], acc, _fun), do: acc @spec sum(xs::[integer()]) :: r::integer() # az xs elemeinek az összege r def sum([x|xs]), do: x + sum xs def sum([]), do: 0 def test(0) do IO.inspect Dp.Fun.stir_2 {2, 3} # hívható modulnévvel is IO.inspect stir_2 {12, 3} IO.inspect stir_2 {6,5} IO.inspect stir_2 "kavart" end def test(1) do IO.inspect picked([3,:a,6,9,0],3) IO.inspect picked_2([3,:a,6,9,0],3) IO.inspect picked_3([3,:a,6,9,0],3) IO.inspect picked_4([3,:a,6,9,0],3) IO.inspect picked_5([3,:a,6,9,0],3) end def test(2) do IO.inspect filt([3, :a, 8, 6, 0], 3) IO.inspect mult([3, 6, 0], 2) IO.inspect picked_3([3,:a,6,9,0],3) IO.inspect picked_4([3,:a,6,9,0],3) IO.inspect picked_5([3,:a,6,9,0],3) end IO.puts "A lokális stir csak modulszintről hívható, " <> "függvényből, modulon kívülről nem." IO.inspect stir.({2, 3}) IO.inspect stir.({12, 3}) IO.inspect stir.({6,5}) IO.inspect stir.("kavart") def test() do test 0 test 1 test 2 end end Dp.Fun.test()