debora-be/mega
0
1# Mega Sena of us winners2 3This LiveBook provides an interactive way to generate and analyze Mega Sena lottery combinations using strategies from Guilhermino Ferreira and Munir W. Niss, combined with statistical analysis.4 5```elixir6Mix.install([7 {:vega_lite, "~> 0.1.8"},8 {:kino, "~> 0.12.0"},9 {:kino_vega_lite, "~> 0.1.11"}10])11 12alias VegaLite, as: Vl13```14 15## Core Generator Module16 17First, let's define our main MegaSena module with all the generation logic:18 19```elixir20defmodule MegaSena do21 @moduledoc """22 Generator for optimized Mega Sena combinations using statistical analysis 23 and expert strategies.24 """25 26 # High frequency numbers according to Ferreira27 @high_frequency_numbers [4, 5, 7, 12, 13, 16, 17, 23, 24, 29, 30, 32, 33,28 37, 38, 41, 42, 43, 47, 49, 50, 51, 53, 54, 58, 59]29 30 # Numbers to avoid according to Niss31 @low_probability_numbers [1, 2, 3, 11, 22, 44, 55, 48, 57]32 33 # Column definitions for vertical line check34 @columns [35 [1, 11, 21, 31, 41, 51],36 [2, 12, 22, 32, 42, 52],37 [3, 13, 23, 33, 43, 53],38 [4, 14, 24, 34, 44, 54],39 [5, 15, 25, 35, 45, 55],40 [6, 16, 26, 36, 46, 56],41 [7, 17, 27, 37, 47, 57],42 [8, 18, 28, 38, 48, 58],43 [9, 19, 29, 39, 49, 59],44 [10, 20, 30, 40, 50, 60]45 ]46 47 # Quadrant definitions48 @quadrants [49 [1, 2, 3, 4, 5, 11, 12, 13, 14, 15, 21, 22, 23, 24, 25],50 [6, 7, 8, 9, 10, 16, 17, 18, 19, 20, 26, 27, 28, 29, 30],51 [31, 32, 33, 34, 35, 41, 42, 43, 44, 45, 51, 52, 53, 54, 55],52 [36, 37, 38, 39, 40, 46, 47, 48, 49, 50, 56, 57, 58, 59, 60]53 ]54 55 def generate_combinations(count \\ 100) do56 generate_combinations(count, MapSet.new(), [])57 end58 59 defp generate_combinations(0, _existing, acc), do: Enum.reverse(acc)60 defp generate_combinations(count, existing, acc) do61 combination = generate_valid_combination(existing)62 combination_key = combination_to_key(combination)63 generate_combinations(64 count - 1,65 MapSet.put(existing, combination_key),66 [combination | acc]67 )68 end69 70 def generate_valid_combination(existing) do71 generate_valid_combination(existing, 0)72 end73 74 defp generate_valid_combination(existing, attempts) when attempts < 1000 do75 combination = generate_base_combination()76 |> Enum.sort()77 78 if is_valid_combination?(combination, existing) do79 combination80 else81 generate_valid_combination(existing, attempts + 1)82 end83 end84 85 defp generate_valid_combination(_existing, _attempts) do86 raise "Unable to generate valid combination after 1000 attempts"87 end88 89 def generate_base_combination do90 high_freq_count = Enum.random(2..3)91 high_freq_numbers = Enum.take_random(@high_frequency_numbers, high_freq_count)92 fill_remaining_numbers(high_freq_numbers, 6 - high_freq_count)93 end94 95 defp fill_remaining_numbers(numbers, count) when count <= 0, do: numbers96 defp fill_remaining_numbers(numbers, count) do97 num = Enum.random(1..60)98 if num not in @low_probability_numbers and num not in numbers do99 fill_remaining_numbers([num | numbers], count - 1)100 else101 fill_remaining_numbers(numbers, count)102 end103 end104 105 def is_valid_combination?(combination, existing) do106 combination_key = combination_to_key(combination)107 108 not has_sequential_numbers?(combination) and109 not is_in_same_column?(combination) and110 is_well_distributed_in_quadrants?(combination) and111 has_balanced_even_odd?(combination) and112 not MapSet.member?(existing, combination_key)113 end114 115 def has_sequential_numbers?(numbers) do116 numbers117 |> Enum.sort()118 |> Enum.chunk_every(2, 1, :discard)119 |> Enum.any?(fn [a, b] -> b - a == 1 end)120 end121 122 def is_in_same_column?(numbers) do123 Enum.any?(@columns, fn column ->124 count = Enum.count(numbers, &(&1 in column))125 count > 1126 end)127 end128 129 def is_well_distributed_in_quadrants?(numbers) do130 numbers_set = MapSet.new(numbers)131 132 Enum.all?(@quadrants, fn quadrant ->133 MapSet.intersection(numbers_set, MapSet.new(quadrant))134 |> MapSet.size()135 |> Kernel.>(0)136 end)137 end138 139 def has_balanced_even_odd?(numbers) do140 even_count = Enum.count(numbers, &(rem(&1, 2) == 0))141 odd_count = length(numbers) - even_count142 abs(even_count - odd_count) <= 1143 end144 145 def combination_to_key(combination) do146 combination147 |> Enum.sort()148 |> Enum.join("-")149 end150end151```152 153## Interactive Controls154 155Let's create some interactive controls to generate combinations:156 157```elixir158number_input = Kino.Input.number("Number of combinations to generate", default: 10)159```160 161## Generate Combinations162 163Now let's generate combinations based on the input:164 165```elixir166combinations = number_input167|> Kino.Input.read()168|> MegaSena.generate_combinations()169 170# Display the combinations in a nice format171combinations172|> Enum.with_index(1)173|> Enum.map(fn {combo, index} ->174 "#{String.pad_leading("#{index}", 3)}: #{MegaSena.combination_to_key(combo)}"175end)176|> Enum.join("\n")177|> IO.puts()178```179 180## Analysis and Visualization181 182Let's analyze and visualize the generated combinations:183 184```elixir185# Prepare data for visualization186number_frequencies = combinations187|> Enum.flat_map(& &1)188|> Enum.reduce(%{}, fn num, acc ->189 Map.update(acc, num, 1, & &1 + 1)190end)191|> Enum.map(fn {num, count} ->192 %{193 number: num,194 frequency: count,195 type: if(num in MegaSena.high_frequency_numbers, do: "High Frequency", else: "Normal")196 }197end)198 199# Create visualization200Vl.new(width: 600, height: 400)201|> Vl.data_from_values(number_frequencies)202|> Vl.mark(:bar)203|> Vl.encode_field(:x, "number", type: :ordinal, title: "Number")204|> Vl.encode_field(:y, "frequency", type: :quantitative, title: "Frequency")205|> Vl.encode_field(:color, "type", type: :nominal)206|> Vl.config(view: [stroke: nil])207|> Vl.config(axis: [grid: false])208|> Vl.title("Number Frequencies in Generated Combinations")209```210 211## Statistics212 213Let's calculate some statistics about our generated combinations:214 215```elixir216stats = combinations217|> Enum.reduce(%{even_count: 0, odd_count: 0, quadrant_counts: %{1 => 0, 2 => 0, 3 => 0, 4 => 0}}, 218 fn combination, acc ->219 even_count = Enum.count(combination, &(rem(&1, 2) == 0))220 odd_count = 6 - even_count221 222 quadrant_counts = combination223 |> Enum.reduce(acc.quadrant_counts, fn num, qacc ->224 quadrant = Enum.find_index(MegaSena.quadrants, &(num in &1)) + 1225 Map.update(qacc, quadrant, 1, & &1 + 1)226 end)227 228 %{229 even_count: acc.even_count + even_count,230 odd_count: acc.odd_count + odd_count,231 quadrant_counts: quadrant_counts232 }233end)234 235# Display statistics236IO.puts("""237Statistics for #{length(combinations)} combinations:238 239Even numbers: #{stats.even_count} (#{Float.round(stats.even_count / (length(combinations) * 6) * 100, 2)}%)240Odd numbers: #{stats.odd_count} (#{Float.round(stats.odd_count / (length(combinations) * 6) * 100, 2)}%)241 242Quadrant distribution:243#{Enum.map(stats.quadrant_counts, fn {q, count} -> 244 " Quadrant #{q}: #{count} (#{Float.round(count / (length(combinations) * 6) * 100, 2)}%)"245end) |> Enum.join("\n")}246""")247```248 249## Export Combinations250 251Let's create a way to export our combinations:252 253```elixir254frame = Kino.Frame.new()255 256export_button = Kino.Control.button("Export Combinations")257 258Kino.listen(export_button, fn _event -> 259 content = combinations260 |> Enum.with_index(1)261 |> Enum.map(fn {combo, index} ->262 "#{String.pad_leading("#{index}", 3)}: #{MegaSena.combination_to_key(combo)}"263 end)264 |> Enum.join("\n")265 266 Kino.Frame.render(frame, content)267end)268 269frame270```271 272## Validation Tool273 274Let's create a tool to validate custom combinations:275 276```elixir277combination_input = Kino.Input.text("Enter combination (e.g., 1-2-3-4-5-6)")278 279validate_button = Kino.Control.button("Validate Combination")280validation_frame = Kino.Frame.new()281 282Kino.listen(validate_button, fn _event ->283 combination = combination_input284 |> Kino.Input.read()285 |> String.split("-")286 |> Enum.map(&String.trim/1)287 |> Enum.map(&String.to_integer/1)288 |> Enum.sort()289 290 validation_results = [291 {"Sequential numbers", not MegaSena.has_sequential_numbers?(combination)},292 {"Same column numbers", not MegaSena.is_in_same_column?(combination)},293 {"Quadrant distribution", MegaSena.is_well_distributed_in_quadrants?(combination)},294 {"Even/Odd balance", MegaSena.has_balanced_even_odd?(combination)}295 ]296 297 result = """298 Validation Results for #{MegaSena.combination_to_key(combination)}:299 300 #{validation_results |> Enum.map(fn {name, result} ->301 "#{name}: #{if result, do: "✅", else: "❌"}"302 end) |> Enum.join("\n")}303 """304 305 Kino.Frame.render(validation_frame, result)306end)307 308validation_frame309```