Quest 2: From Complex to Clarity

  • Keep top level comments as only solutions, if you want to say something other than a solution put it in a new post. (replies to comments can be whatever)
  • You can send code in code blocks by using three backticks, the code, and then three backticks or use something such as https://topaz.github.io/paste/ if you prefer sending it through a URL

Link to participate: https://everybody.codes/

  • VegOwOtenks@lemmy.world
    link
    fedilink
    arrow-up
    1
    ·
    edit-2
    9 hours ago

    I struggled for a long time because I had nearly the correct results. I had to switch div with quot.

    This puzzle was fun. If you have a visualization, it’s even cooler. (It’s a fractal)

    Haskell Code
    {-# LANGUAGE LambdaCase #-}
    {-# LANGUAGE PatternSynonyms #-}
    {-# OPTIONS_GHC -Wall #-}
    module Main (main) where
    import Text.Read (ReadPrec, Read (readPrec))
    import Data.Functor ((<&>))
    import Data.Text (pattern (:<), Text)
    import qualified Data.Text as Text
    import qualified Data.Text.IO as TextIO
    import Control.Monad ((<$!>))
    import Control.Arrow ((<<<))
    
    newtype Complex = Complex (Int, Int)
    
    instance Read Complex where
      readPrec :: ReadPrec Complex
      readPrec = readPrec <&> \case
        [a, b] -> Complex (a, b)
        _ -> undefined
    
    instance Show Complex where
      show :: Complex -> String
      show (Complex (a, b))= show [a, b]
    
    readAEquals :: Text -> Complex
    readAEquals ('A' :< '=':< rest) = read $ Text.unpack rest
    readAEquals _ = undefined
    
    
    -- >>> Complex (1, 1) `add` Complex (2, 2)
    -- [3,3]
    
    add :: Complex -> Complex -> Complex
    (Complex (x1, y1)) `add` (Complex (x2, y2)) = Complex (x1 + x2, y1 + y2)
    
    -- >>> Complex (2, 5) `times` Complex (5, 7)
    -- [-25,-11]
    
    times :: Complex -> Complex -> Complex
    (Complex (x1, y1)) `times` (Complex (x2, y2)) = Complex (x1 * x2 - y1 * y2, x1 * y2 + x2 * y1)
    
    dividedBy :: Complex -> Complex -> Complex
    (Complex (x1, y1)) `dividedBy` (Complex (x2, y2)) = Complex (x1 `quot` x2, y1 `quot` y2)
    
    step :: Complex -> Complex -> Complex
    step a r = let
     r1 = r `times` r
     r2 = r1 `dividedBy` Complex (10, 10)
     r3 = r2 `add` a
     in r3
    
    zero :: Complex
    zero = Complex (0, 0)
    
    part1 :: Complex -> Complex
    part1 a = iterate (step a) (Complex (0, 0)) !! 3
    
    shouldBeEngraved :: Complex -> Bool
    shouldBeEngraved complexPoint = let
    
      cycleStep :: Complex -> Complex -> Complex
      cycleStep point r = let
        r2 = r `times` r
        r3 = r2 `dividedBy` Complex (100000, 100000)
        in point `add` r3
    
      inRange x = x <= 1000000 && x >= -1000000
    
    
      in all (\ (Complex (x, y)) -> inRange x && inRange y)
        <<< take 101
        <<< iterate (cycleStep complexPoint)
        $ zero
    
    -- >>> shouldBeEngraved $ Complex (35630,-64880)
    -- True
    -- >>> shouldBeEngraved $ Complex (35460, -64910)
    -- False
    -- >>> shouldBeEngraved $ Complex (35630, -64830)
    -- False
    
    part2 :: Complex -> Int
    part2 (Complex (xA, yA)) = let
    
        xB = xA + 1000
        yB = yA + 1000
    
      in length . filter shouldBeEngraved $ do
        x <- [xA, xA+10.. xB]
        y <- [yA, yA+10.. yB]
        pure $ Complex (x, y)
    
    part3 :: Complex -> Int
    part3 (Complex (xA, yA)) = length . filter shouldBeEngraved $ do
      x <- [xA..xA+1000]
      y <- [yA..yA+1000]
      pure $ Complex (x, y)
    
    -- >>> [0, 10..100]
    -- [0,10,20,30,40,50,60,70,80,90,100]
    
    main :: IO ()
    main = do
      a <- readAEquals <$!> TextIO.getContents
      print $ part1 a
      print $ part2 a
      print $ part3 a
    

    My girlfriend is learning python, we are taking on the challenges together, today I may upload her solution:

    python
    A=[-3344,68783]
    R = [0, 0]
    B= [A[0]+1000, A[1]+1000]
    pointsengraved = 0
    cycleright = 0
    
    
    for i in range(A[1], B[1]+1):
        for j in range(A[0], B[0]+1):
            for k in range(100):
                R = [int(R[0] * R[0] - R[1] * R[1]), int(R[0] * R[1] + R[1] * R[0])]
                R = [int(R[0] / 100000), int(R[1] / 100000)]
                R = [int(R[0] + j), int(R[1] + i)]
                if -1000000>R[0] or R[0]>1000000 or -1000000>R[1] or R[1]>1000000:
                    #print(".", end="")
                    break
                cycleright += 1
            if cycleright == 100:
                pointsengraved += 1
                #print("+", end="")
            cycleright = 0
            R = [0, 0]
        #print()
    
    print(pointsengraved)
    

    The commented out print statements produce an ascii map of the set, which can be cool to view at the right font size.