module Main exposing ( Choice , Color(..) , Edge(..) , EdgeColor(..) , EdgeVertex(..) , Face(..) , Model , Msg(..) , Vertex(..) , VertexPair , baseGuesses , colorsToOrder , init , main , pickRandomColor , remainingBlue , remainingGreen , remainingOrange , remainingPink , remainingYellow , update , view ) import Browser import Html exposing (Attribute, Html, div, i, text) import Html.Attributes exposing (..) import Html.Events exposing (onInput) import List.Extra exposing (zip, zip3) import Random -- MAIN main = Browser.element { init = init , update = update , view = view , subscriptions = \_ -> Sub.none } -- MODEL type alias Model = { randoms : List Float , candidate : List EdgeColor , candidatePasses : Bool , triesLeft : Int } -- order matters a LOT tries = 50000 init : () -> ( Model, Cmd Msg ) init _ = ( { randoms = [], candidate = [], candidatePasses = False, triesLeft = tries }, newGuesses ) -- UPDATE type Msg = GetNextRandoms (List Float) | NoOp fractions : Random.Generator (List Float) fractions = Random.list (List.length baseGuesses) (Random.float 0 1) newGuesses : Cmd Msg newGuesses = Random.generate GetNextRandoms fractions update : Msg -> Model -> ( Model, Cmd Msg ) update msg model = case msg of GetNextRandoms randoms -> let candidate = createCandidate randoms icosahedron baseGuesses candidatePasses = checkCandidate candidate newTriesLeft = model.triesLeft - 1 nextCommand = if model.triesLeft > 0 && candidatePasses == False then newGuesses else Cmd.none -- trumm2 = -- Debug.log "tries left" (Debug.toString newTriesLeft) in ( { model | randoms = randoms , candidate = candidate , candidatePasses = candidatePasses , triesLeft = newTriesLeft } , nextCommand ) -- in GetNextRandoms branch, have some condition to create a guess solution, check it -- and conditionally ask to guess again via newGuesses if the solution was not a success. NoOp -> ( model, Cmd.none ) createCandidate : List Float -> List EdgeVertex -> List (List Color) -> List EdgeColor createCandidate randoms vertexPairs possibleGuesses = let randomColors = pickRandomRemainingColor randoms initialRemainingColors [] guesses = baseColorSequence ++ randomColors zipSoup = zip vertexPairs guesses -- zip3 randoms vertexPairs possibleGuesses edgeColors = List.map zipSoupMapFunction zipSoup -- trumm = -- Debug.log "zip Soup!" zipSoup -- trumm = -- Debug.log "mah candidate!" edgeColors -- List.map zipSoupMapFunction zipSoup -- trumm = -- --Debug.log "edge colors!!!" edgeColors -- Debug.log "allcolors" guesses in edgeColors zipSoupMapFunction : ( EdgeVertex, Color ) -> EdgeColor zipSoupMapFunction ( edgeVertex, color ) = edgeVertexToEdgeColor edgeVertex color -- zipSoupMapFunction : ( Float, EdgeVertex, List Color ) -> EdgeColor -- zipSoupMapFunction ( randomChance, vertexPair, guessOptions ) = -- edgeVertexToEdgeColor vertexPair (pickRandomColor randomChance guessOptions) checkCandidate : List EdgeColor -> Bool checkCandidate edgeColors = let counts = List.foldl countVertex initialVertexColorCounters edgeColors countsPass = List.foldl checkCounts True counts in countsPass checkCounts : VertexColorCounter -> Bool -> Bool checkCounts colorCounter acc = if acc == False then acc else case colorCounter of Counter _ ( _, 1 ) ( _, 1 ) ( _, 1 ) ( _, 1 ) ( _, 1 ) -> True Counter _ _ _ _ _ _ -> False countVertex : EdgeColor -> List VertexColorCounter -> List VertexColorCounter countVertex edgeColor acc = let ( v1, v2, c ) = unboxEdgeColor edgeColor blah = List.map (\(Counter vCounting ( p, p_int ) ( g, g_int ) ( b, b_int ) ( o, o_int ) ( y, y_int )) -> if vCounting == v1 || vCounting == v2 then case c of P -> Counter vCounting ( p, p_int + 1 ) ( g, g_int ) ( b, b_int ) ( o, o_int ) ( y, y_int ) G -> Counter vCounting ( p, p_int ) ( g, g_int + 1 ) ( b, b_int ) ( o, o_int ) ( y, y_int ) B -> Counter vCounting ( p, p_int ) ( g, g_int ) ( b, b_int + 1 ) ( o, o_int ) ( y, y_int ) O -> Counter vCounting ( p, p_int ) ( g, g_int ) ( b, b_int ) ( o, o_int + 1 ) ( y, y_int ) Y -> Counter vCounting ( p, p_int ) ( g, g_int ) ( b, b_int ) ( o, o_int ) ( y, y_int + 1 ) else Counter vCounting ( p, p_int ) ( g, g_int ) ( b, b_int ) ( o, o_int ) ( y, y_int ) ) acc in blah pickRandomColor : Float -> List Color -> Color pickRandomColor randomFloat colors = let colorsLength = List.length colors index = ceiling (randomFloat * toFloat colorsLength) - 1 grabbedColor = List.head (List.drop index colors) in case grabbedColor of Just c -> c Nothing -> P -- Takes in 25 floats and remaining colors, and assigns them all -- doesn't try to interact with possibleGuesses (yet) pickRandomRemainingColor : List Float -> RemainingColors -> List Color -> List Color pickRandomRemainingColor floats (Rem ( p, p_int ) ( g, g_int ) ( b, b_int ) ( o, o_int ) ( y, y_int )) acc = if List.length floats == 0 then acc else if p_int == 0 && g_int == 0 && b_int == 0 && o_int == 0 && y_int == 0 then acc else let availableColors = maybeAllowColor ( y, y_int ) [] |> maybeAllowColor ( o, o_int ) |> maybeAllowColor ( b, b_int ) |> maybeAllowColor ( g, g_int ) |> maybeAllowColor ( p, p_int ) chosenColor = case floats of x :: xs -> pickRandomColor x availableColors _ -> P newRemainingColors = case chosenColor of P -> Rem ( p, p_int - 1 ) ( g, g_int ) ( b, b_int ) ( o, o_int ) ( y, y_int ) G -> Rem ( p, p_int ) ( g, g_int - 1 ) ( b, b_int ) ( o, o_int ) ( y, y_int ) B -> Rem ( p, p_int ) ( g, g_int ) ( b, b_int - 1 ) ( o, o_int ) ( y, y_int ) O -> Rem ( p, p_int ) ( g, g_int ) ( b, b_int ) ( o, o_int - 1 ) ( y, y_int ) Y -> Rem ( p, p_int ) ( g, g_int ) ( b, b_int ) ( o, o_int ) ( y, y_int - 1 ) in case List.tail floats of Just remainingFloats -> pickRandomRemainingColor remainingFloats newRemainingColors (chosenColor :: acc) _ -> acc maybeAllowColor : ColorCount -> List Color -> List Color maybeAllowColor ( color, count ) list = if count > 0 then color :: list else list -- VIEW view : Model -> Html Msg view model = if model.candidatePasses then div [] [ div [] [ text (Debug.toString model.candidate) ] ] else if model.triesLeft == -1 then div [] [ text ("unable to find solution after " ++ String.fromInt tries ++ " guesses.") ] else i [] [] -- TYPES type Color = P | G | B | O | Y type Face = F_01 | F_02 | F_03 | F_04 | F_05 | F_06 | F_07 | F_08 | F_09 | F_10 | F_11 | F_12 | F_13 | F_14 | F_15 | F_16 | F_17 | F_18 | F_19 | F_20 type Vertex = V_01 | V_02 | V_03 | V_04 | V_05 | V_06 | V_07 | V_08 | V_09 | V_10 | V_11 | V_12 type VertexColorCounter = Counter Vertex ColorCount ColorCount ColorCount ColorCount ColorCount initialVertexColorCounters : List VertexColorCounter initialVertexColorCounters = [ Counter V_01 ( P, 0 ) ( G, 0 ) ( B, 0 ) ( O, 0 ) ( Y, 0 ) , Counter V_02 ( P, 0 ) ( G, 0 ) ( B, 0 ) ( O, 0 ) ( Y, 0 ) , Counter V_03 ( P, 0 ) ( G, 0 ) ( B, 0 ) ( O, 0 ) ( Y, 0 ) , Counter V_04 ( P, 0 ) ( G, 0 ) ( B, 0 ) ( O, 0 ) ( Y, 0 ) , Counter V_05 ( P, 0 ) ( G, 0 ) ( B, 0 ) ( O, 0 ) ( Y, 0 ) , Counter V_06 ( P, 0 ) ( G, 0 ) ( B, 0 ) ( O, 0 ) ( Y, 0 ) , Counter V_07 ( P, 0 ) ( G, 0 ) ( B, 0 ) ( O, 0 ) ( Y, 0 ) , Counter V_08 ( P, 0 ) ( G, 0 ) ( B, 0 ) ( O, 0 ) ( Y, 0 ) , Counter V_09 ( P, 0 ) ( G, 0 ) ( B, 0 ) ( O, 0 ) ( Y, 0 ) , Counter V_10 ( P, 0 ) ( G, 0 ) ( B, 0 ) ( O, 0 ) ( Y, 0 ) , Counter V_11 ( P, 0 ) ( G, 0 ) ( B, 0 ) ( O, 0 ) ( Y, 0 ) , Counter V_12 ( P, 0 ) ( G, 0 ) ( B, 0 ) ( O, 0 ) ( Y, 0 ) ] type Edge = E_01 | E_02 | E_03 | E_04 | E_05 | E_06 | E_07 | E_08 | E_09 | E_10 | E_11 | E_12 | E_13 | E_14 | E_15 | E_16 | E_17 | E_18 | E_19 | E_20 | E_21 | E_22 | E_23 | E_24 | E_25 | E_26 | E_27 | E_28 | E_29 | E_30 type alias Choice = ( Vertex, Vertex, Color ) type alias VertexPair = ( Vertex, Vertex ) type EdgeColor = EC_01 Vertex Vertex Color | EC_02 Vertex Vertex Color | EC_03 Vertex Vertex Color | EC_04 Vertex Vertex Color | EC_05 Vertex Vertex Color | EC_06 Vertex Vertex Color | EC_07 Vertex Vertex Color | EC_08 Vertex Vertex Color | EC_09 Vertex Vertex Color | EC_10 Vertex Vertex Color | EC_11 Vertex Vertex Color | EC_12 Vertex Vertex Color | EC_13 Vertex Vertex Color | EC_14 Vertex Vertex Color | EC_15 Vertex Vertex Color | EC_16 Vertex Vertex Color | EC_17 Vertex Vertex Color | EC_18 Vertex Vertex Color | EC_19 Vertex Vertex Color | EC_20 Vertex Vertex Color | EC_21 Vertex Vertex Color | EC_22 Vertex Vertex Color | EC_23 Vertex Vertex Color | EC_24 Vertex Vertex Color | EC_25 Vertex Vertex Color | EC_26 Vertex Vertex Color | EC_27 Vertex Vertex Color | EC_28 Vertex Vertex Color | EC_29 Vertex Vertex Color | EC_30 Vertex Vertex Color type EdgeVertex = EV_01 Vertex Vertex | EV_02 Vertex Vertex | EV_03 Vertex Vertex | EV_04 Vertex Vertex | EV_05 Vertex Vertex | EV_06 Vertex Vertex | EV_07 Vertex Vertex | EV_08 Vertex Vertex | EV_09 Vertex Vertex | EV_10 Vertex Vertex | EV_11 Vertex Vertex | EV_12 Vertex Vertex | EV_13 Vertex Vertex | EV_14 Vertex Vertex | EV_15 Vertex Vertex | EV_16 Vertex Vertex | EV_17 Vertex Vertex | EV_18 Vertex Vertex | EV_19 Vertex Vertex | EV_20 Vertex Vertex | EV_21 Vertex Vertex | EV_22 Vertex Vertex | EV_23 Vertex Vertex | EV_24 Vertex Vertex | EV_25 Vertex Vertex | EV_26 Vertex Vertex | EV_27 Vertex Vertex | EV_28 Vertex Vertex | EV_29 Vertex Vertex | EV_30 Vertex Vertex icosahedron = [ EV_01 V_01 V_02 , EV_02 V_01 V_03 , EV_03 V_01 V_04 , EV_04 V_01 V_05 , EV_05 V_01 V_06 , EV_06 V_02 V_03 , EV_07 V_02 V_06 , EV_08 V_02 V_07 , EV_09 V_02 V_11 , EV_10 V_03 V_04 , EV_11 V_03 V_07 , EV_12 V_03 V_08 , EV_13 V_04 V_05 , EV_14 V_04 V_08 , EV_15 V_04 V_09 , EV_16 V_05 V_06 , EV_17 V_05 V_09 , EV_18 V_05 V_10 , EV_19 V_06 V_10 , EV_20 V_06 V_11 , EV_21 V_07 V_08 , EV_22 V_07 V_11 , EV_23 V_07 V_12 , EV_24 V_08 V_09 , EV_25 V_08 V_12 , EV_26 V_09 V_10 , EV_27 V_09 V_12 , EV_28 V_10 V_11 , EV_29 V_10 V_12 , EV_30 V_11 V_12 ] unboxEdgeColor : EdgeColor -> ( Vertex, Vertex, Color ) unboxEdgeColor edgeColor = case edgeColor of EC_01 v1 v2 c -> ( v1, v2, c ) EC_02 v1 v2 c -> ( v1, v2, c ) EC_03 v1 v2 c -> ( v1, v2, c ) EC_04 v1 v2 c -> ( v1, v2, c ) EC_05 v1 v2 c -> ( v1, v2, c ) EC_06 v1 v2 c -> ( v1, v2, c ) EC_07 v1 v2 c -> ( v1, v2, c ) EC_08 v1 v2 c -> ( v1, v2, c ) EC_09 v1 v2 c -> ( v1, v2, c ) EC_10 v1 v2 c -> ( v1, v2, c ) EC_11 v1 v2 c -> ( v1, v2, c ) EC_12 v1 v2 c -> ( v1, v2, c ) EC_13 v1 v2 c -> ( v1, v2, c ) EC_14 v1 v2 c -> ( v1, v2, c ) EC_15 v1 v2 c -> ( v1, v2, c ) EC_16 v1 v2 c -> ( v1, v2, c ) EC_17 v1 v2 c -> ( v1, v2, c ) EC_18 v1 v2 c -> ( v1, v2, c ) EC_19 v1 v2 c -> ( v1, v2, c ) EC_20 v1 v2 c -> ( v1, v2, c ) EC_21 v1 v2 c -> ( v1, v2, c ) EC_22 v1 v2 c -> ( v1, v2, c ) EC_23 v1 v2 c -> ( v1, v2, c ) EC_24 v1 v2 c -> ( v1, v2, c ) EC_25 v1 v2 c -> ( v1, v2, c ) EC_26 v1 v2 c -> ( v1, v2, c ) EC_27 v1 v2 c -> ( v1, v2, c ) EC_28 v1 v2 c -> ( v1, v2, c ) EC_29 v1 v2 c -> ( v1, v2, c ) EC_30 v1 v2 c -> ( v1, v2, c ) edgeVertexToEdgeColor : EdgeVertex -> Color -> EdgeColor edgeVertexToEdgeColor edgeVertex c = case edgeVertex of EV_01 v1 v2 -> EC_01 v1 v2 c EV_02 v1 v2 -> EC_02 v1 v2 c EV_03 v1 v2 -> EC_03 v1 v2 c EV_04 v1 v2 -> EC_04 v1 v2 c EV_05 v1 v2 -> EC_05 v1 v2 c EV_06 v1 v2 -> EC_06 v1 v2 c EV_07 v1 v2 -> EC_07 v1 v2 c EV_08 v1 v2 -> EC_08 v1 v2 c EV_09 v1 v2 -> EC_09 v1 v2 c EV_10 v1 v2 -> EC_10 v1 v2 c EV_11 v1 v2 -> EC_11 v1 v2 c EV_12 v1 v2 -> EC_12 v1 v2 c EV_13 v1 v2 -> EC_13 v1 v2 c EV_14 v1 v2 -> EC_14 v1 v2 c EV_15 v1 v2 -> EC_15 v1 v2 c EV_16 v1 v2 -> EC_16 v1 v2 c EV_17 v1 v2 -> EC_17 v1 v2 c EV_18 v1 v2 -> EC_18 v1 v2 c EV_19 v1 v2 -> EC_19 v1 v2 c EV_20 v1 v2 -> EC_20 v1 v2 c EV_21 v1 v2 -> EC_21 v1 v2 c EV_22 v1 v2 -> EC_22 v1 v2 c EV_23 v1 v2 -> EC_23 v1 v2 c EV_24 v1 v2 -> EC_24 v1 v2 c EV_25 v1 v2 -> EC_25 v1 v2 c EV_26 v1 v2 -> EC_26 v1 v2 c EV_27 v1 v2 -> EC_27 v1 v2 c EV_28 v1 v2 -> EC_28 v1 v2 c EV_29 v1 v2 -> EC_29 v1 v2 c EV_30 v1 v2 -> EC_30 v1 v2 c viewColor : Color -> String viewColor color = case color of P -> "Pink" G -> "Green" B -> "Blue" O -> "Orange" Y -> "Yellow" viewVertex : Vertex -> String viewVertex vertex = case vertex of V_01 -> "V_01" V_02 -> "V_02" V_03 -> "V_03" V_04 -> "V_04" V_05 -> "V_05" V_06 -> "V_06" V_07 -> "V_07" V_08 -> "V_08" V_09 -> "V_09" V_10 -> "V_10" V_11 -> "V_11" V_12 -> "V_12" viewEdgeVertex : EdgeVertex -> String viewEdgeVertex edgeVertex = case edgeVertex of EV_01 v1 v2 -> viewVertex v1 ++ " <-> " ++ viewVertex v2 EV_02 v1 v2 -> viewVertex v1 ++ " <-> " ++ viewVertex v2 EV_03 v1 v2 -> viewVertex v1 ++ " <-> " ++ viewVertex v2 EV_04 v1 v2 -> viewVertex v1 ++ " <-> " ++ viewVertex v2 EV_05 v1 v2 -> viewVertex v1 ++ " <-> " ++ viewVertex v2 EV_06 v1 v2 -> viewVertex v1 ++ " <-> " ++ viewVertex v2 EV_07 v1 v2 -> viewVertex v1 ++ " <-> " ++ viewVertex v2 EV_08 v1 v2 -> viewVertex v1 ++ " <-> " ++ viewVertex v2 EV_09 v1 v2 -> viewVertex v1 ++ " <-> " ++ viewVertex v2 EV_10 v1 v2 -> viewVertex v1 ++ " <-> " ++ viewVertex v2 EV_11 v1 v2 -> viewVertex v1 ++ " <-> " ++ viewVertex v2 EV_12 v1 v2 -> viewVertex v1 ++ " <-> " ++ viewVertex v2 EV_13 v1 v2 -> viewVertex v1 ++ " <-> " ++ viewVertex v2 EV_14 v1 v2 -> viewVertex v1 ++ " <-> " ++ viewVertex v2 EV_15 v1 v2 -> viewVertex v1 ++ " <-> " ++ viewVertex v2 EV_16 v1 v2 -> viewVertex v1 ++ " <-> " ++ viewVertex v2 EV_17 v1 v2 -> viewVertex v1 ++ " <-> " ++ viewVertex v2 EV_18 v1 v2 -> viewVertex v1 ++ " <-> " ++ viewVertex v2 EV_19 v1 v2 -> viewVertex v1 ++ " <-> " ++ viewVertex v2 EV_20 v1 v2 -> viewVertex v1 ++ " <-> " ++ viewVertex v2 EV_21 v1 v2 -> viewVertex v1 ++ " <-> " ++ viewVertex v2 EV_22 v1 v2 -> viewVertex v1 ++ " <-> " ++ viewVertex v2 EV_23 v1 v2 -> viewVertex v1 ++ " <-> " ++ viewVertex v2 EV_24 v1 v2 -> viewVertex v1 ++ " <-> " ++ viewVertex v2 EV_25 v1 v2 -> viewVertex v1 ++ " <-> " ++ viewVertex v2 EV_26 v1 v2 -> viewVertex v1 ++ " <-> " ++ viewVertex v2 EV_27 v1 v2 -> viewVertex v1 ++ " <-> " ++ viewVertex v2 EV_28 v1 v2 -> viewVertex v1 ++ " <-> " ++ viewVertex v2 EV_29 v1 v2 -> viewVertex v1 ++ " <-> " ++ viewVertex v2 EV_30 v1 v2 -> viewVertex v1 ++ " <-> " ++ viewVertex v2 baseGuesses = [ [ P ] , [ G ] , [ B ] , [ O ] , [ Y ] , [ B, O, Y ] , [ G, B, O ] , [ G, B, O, Y ] , [ G, B, O, Y ] , [ P, O, Y ] , [ P, B, O, Y ] , [ P, B, O, Y ] , [ P, G, Y ] , [ P, G, O, Y ] , [ P, G, O, Y ] , [ P, G, B ] , [ P, G, B, Y ] , [ P, G, B, Y ] , [ P, G, B, O ] , [ P, G, B, O ] , [ P, G, B, O, Y ] , [ P, G, B, O, Y ] , [ P, G, B, O, Y ] , [ P, G, B, O, Y ] , [ P, G, B, O, Y ] , [ P, G, B, O, Y ] , [ P, G, B, O, Y ] , [ P, G, B, O, Y ] , [ P, G, B, O, Y ] , [ P, G, B, O, Y ] ] baseColorSequence : List Color baseColorSequence = [ P, G, B, O, Y ] remainingPink = [ P, P, P, P, P ] remainingGreen = [ G, G, G, G, G ] remainingBlue = [ B, B, B, B, B ] remainingOrange = [ O, O, O, O, O ] remainingYellow = [ Y, Y, Y, Y, Y ] type alias ColorCount = ( Color, Int ) type RemainingColors = Rem ColorCount ColorCount ColorCount ColorCount ColorCount initialRemainingColors : RemainingColors initialRemainingColors = Rem ( P, 5 ) ( G, 5 ) ( B, 5 ) ( O, 5 ) ( Y, 5 ) colorsToOrder = remainingPink ++ remainingGreen ++ remainingBlue ++ remainingOrange ++ remainingYellow