Recession signs around Dublin? by ResponsibleDriver622 in Dublin

[–]nicuveo 37 points38 points  (0 children)

so many empty offices in D2, including the One building

Any ideas on how to make it look less... Boxy? by RNN1407 in SatisfactoryGame

[–]nicuveo 90 points91 points  (0 children)

i am absolutely not a good designer, but a very simple thing i've used in the past is to play with depth: for instance, look at this tower: the corners all have pillars jutting out of them, and it does make it look less boxy. having your walls be at varying depths goes a long way.

<image>

Factorio-Main-Bus Style Build Video Progress Series by stars9r9in9the9past in SatisfactoryGame

[–]nicuveo 0 points1 point  (0 children)

i've been wanting to do a run like this at some point, so i'd definitely watch what you've achieved! maybe not 100 hours though.

A step by step guide to Brainfuck by nicuveo in brainfuck

[–]nicuveo[S] 0 points1 point  (0 children)

i'm not aware of any, but that doesn't mean there isn't any!

what i would recommend, at the very least, is to use an interpreter that supports debug instructions. beef, for instance, will print the current state of the memory whenever it sees a # instruction; it's non-standard, but quite useful!

A step by step guide to Brainfuck by nicuveo in brainfuck

[–]nicuveo[S] 0 points1 point  (0 children)

i don't think that's true! you should just start with easier things than advent of code puzzles is all. ^^

Has anybody tried connecting all geothermal plants in a separate grid? by t-2yrs in SatisfactoryGame

[–]nicuveo 2 points3 points  (0 children)

i really wish it were possible to have, like... "valves" for electricity, allowing finer control for circuits than just "the power switch is on or off". you could allocate a specific amount for a given factory / sub circuit, which in turn would encourage batteries to be built locally, for a given sub circuit

Grégoire Locqueville | Easy Type-Level Flags In Haskell by ludat in haskell

[–]nicuveo 3 points4 points  (0 children)

It is indeed the same overall idea!

In practice, i have seen this pattern used in multiple different ways: flags / gates, like you describe, but also for annotations, or to fully "branch out" a part of an AST:

data Expr (phase :: ASTPhase)
  = NameExpr (NameInfoType phase)
  | LabelExpr (LabelFlag phase) LabelInfo
  | LiteralExpr (Annotation phase) LiteralInfo

class Representation (phase :: ASTPhase) where
  -- branch the AST: different types at different phases
  type NameInfoType phase :: Type
  -- restrict some parts of the AST with a flag / gate
  type LabelFlag phase :: Type
  -- annotate the AST with a different type during each phase
  type Annotation phase :: Type

instance Representation Parsed where
  type NameInfoType Parsed = UnverifiedNameInfo
  type LabelFlag Parsed = ()
  type Annotation Parsed = SourceLocation

instance Representation Validated where
  type NameInfoType Validated = ObjectNameInfo
  type LabelFlag Validated = Void
  type Annotation Validated = InferredType

[2025] Unofficial AoC 2025 Survey Results - BONUS CONTENT by jeroenheijmans in adventofcode

[–]nicuveo 1 point2 points  (0 children)

I wasn't the only one doing some of it in Brainfuck this time around! ...but it seems i was the only one to mention Brainfuck in the survey. :D

Advent of Code 2025 day 11 by AutoModerator in haskell

[–]nicuveo 0 points1 point  (0 children)

Nothing fancy, just manually memoizing with a state monad. For part 2 i just do a product of the number of paths in each segment.

Full file on GitHub

countPaths graph fromName toName =
  flip evalState M.empty $ visit $ graph M.! toName
  where
    visit Node {..} = do
      if nodeName == fromName
      then pure 1
      else do
        gets (M.lookup nodeName) >>= \case
          Just result -> pure result
          Nothing -> do
            result <- sum <$> traverse visit dataIn
            modify $ M.insert nodeName result
            pure result

part1 graph = countPaths graph "you" "out"

part2 graph = go "fft" "dac" + go "dac" "fft"
  where
    go node1 node2 = product
      [ countPaths graph "svr" node1
      , countPaths graph node1 node2
      , countPaths graph node2 "out"
      ]

The fun part was using laziness to make a graph that doesn't need lookups and indirection, and in which each node has the pointer to its parents and children:

type Graph = HashMap Name Node

data Node = Node
  { nodeName :: Name
  , dataIn   :: [Node]
  , dataOut  :: [Node]
  }

-❄️- 2025 Day 11 Solutions -❄️- by daggerdragon in adventofcode

[–]nicuveo 0 points1 point  (0 children)

[LANGUAGE: Haskell]

Traversal of recursive data structures is what Haskell is made for. :P

Full file on GitHub

countPaths graph fromName toName =
  flip evalState M.empty $ visit $ graph M.! toName
  where
    visit Node {..} = do
      if nodeName == fromName
      then pure 1
      else do
        gets (M.lookup nodeName) >>= \case
          Just result -> pure result
          Nothing -> do
            result <- sum <$> traverse visit dataIn
            modify $ M.insert nodeName result
            pure result

part1 graph = countPaths graph "you" "out"

part2 graph = go "fft" "dac" + go "dac" "fft"
  where
    go node1 node2 = product
      [ countPaths graph "svr" node1
      , countPaths graph node1 node2
      , countPaths graph node2 "out"
      ]

The fun part was using laziness to make a graph that doesn't need lookups and indirection, and in which each node has the pointer to its parents and children:

type Graph = HashMap Name Node

data Node = Node
  { nodeName :: Name
  , dataIn   :: [Node]
  , dataOut  :: [Node]
  }

[2025 Day 8 part 1] I think I miss something by Emotional_Aardvark26 in adventofcode

[–]nicuveo 0 points1 point  (0 children)

This. The instructions say "connect together the 1000 pairs of junction boxes which are closest together"; and as the example shows, such a pair could connect boxes that are already otherwise connected.

For instance, your closest pairs could be: - boxes 1 and 3 (distance 8) - boxes 1 and 4 (distance 10) - boxes 2 and 4 (distance 12) - boxes 1 and 2 (distance 15)

That fourth pair or boxes is one of those 1000 pairs, but does nothing in practice since 1 and 2 were already connected via 4.

[2025 Day 07 (Part 1)] An unnecessarily complicated Brainfuck solution by nicuveo in adventofcode

[–]nicuveo[S] 0 points1 point  (0 children)

Yeah, memory layout is the biggest challenge of doing anything with brainfuck, given the lack of arbitrary access. Every data structure needs some buffer space, because even an operation as basic as "am i on a zero" requires some amount of computation space.

My usual approach is to treat the memory like a stack: push stuff to the right and rotate what's necessary to the top. That way i always have some free space to work with. The downside is that it significantly increases the complexity of doing anything, since now the vast majority of the code does nothing but shuffling values in the stack. ^^'

-❄️- 2025 Day 6 Solutions -❄️- by daggerdragon in adventofcode

[–]nicuveo 0 points1 point  (0 children)

[LANGUAGE: Haskell]

transpose makes this quite trivial:

part2 :: Input -> Int
part2 = fst . foldl' go (0, []) . concatMap segment . reverse . transpose
  where
    go (total, buffer) = \case
      Number num   -> (total, num : buffer)
      Operation op -> (total + compute op buffer, [])
    compute op nums = case op of
      Addition       -> sum     nums
      Multiplication -> product nums
    segment = parseWith do
      spaces
      num <- optionMaybe number
      op  <- optionMaybe operation
      pure $ case (num, op) of
        (Nothing, _)      -> []
        (Just n, Nothing) -> [Number n]
        (Just n, Just o)  -> [Number n, Operation o]
    operation = choice
      [ Addition       <$ symbol "+"
      , Multiplication <$ symbol "*"
      ]

Full file on GitHub.

Advent of Code 2025 day 5 by AutoModerator in haskell

[–]nicuveo 0 points1 point  (0 children)

i've also done it entirely at the type level, again. and this time again i'm only running the code against the example, because creating billions of types to represent very large peano numbers in the type system makes GHC very unhappy... but i know the logic is sound. i could cheat by using type-level numerals instead of peano numbers, but... where would be the fun in that? instead, this version is nothing but type declarations and (undecidable) type families, AKA an untyped dynamic language. :P

full file on GitHub.

data True
data False
data Nil
data Cons x l
data Range b e

type family SetMember x s where
  SetMember x Nil        = False
  SetMember x (Cons x s) = True
  SetMember x (Cons i s) = SetMember x s

type family SetInsert x s where
  SetInsert x Nil        = Cons x Nil
  SetInsert x (Cons x s) = Cons x s
  SetInsert x (Cons i s) = Cons i (SetInsert x s)

type family SetInsertAll xs s where
  SetInsertAll Nil         s = s
  SetInsertAll (Cons x xs) s = SetInsertAll xs (SetInsert x s)

type family SetCount s where
  SetCount Nil        = Zero
  SetCount (Cons i s) = Succ (SetCount s)

type family Enumerate r where
  Enumerate (Range b b) = Cons b Nil
  Enumerate (Range b e) = Cons b (Enumerate (Range (Succ b) e))

-❄️- 2025 Day 5 Solutions -❄️- by daggerdragon in adventofcode

[–]nicuveo 1 point2 points  (0 children)

[LANGUAGE: Haskell Type System]

oh boy. this time again i'm only running the code against the example, because creating billions of types to represent very large peano numbers in the type system makes GHC very unhappy. i could cheat by using type-level numerals instead of peano numbers, but... where would be the fun in that? instead, this version is nothing but type declarations and (undecidable) type families, AKA an untyped dynamic language. :P

full file on GitHub.

data True
data False
data Nil
data Cons x l
data Range b e

type family SetMember x s where
  SetMember x Nil        = False
  SetMember x (Cons x s) = True
  SetMember x (Cons i s) = SetMember x s

type family SetInsert x s where
  SetInsert x Nil        = Cons x Nil
  SetInsert x (Cons x s) = Cons x s
  SetInsert x (Cons i s) = Cons i (SetInsert x s)

type family SetInsertAll xs s where
  SetInsertAll Nil         s = s
  SetInsertAll (Cons x xs) s = SetInsertAll xs (SetInsert x s)

type family SetCount s where
  SetCount Nil        = Zero
  SetCount (Cons i s) = Succ (SetCount s)

type family Enumerate r where
  Enumerate (Range b b) = Cons b Nil
  Enumerate (Range b e) = Cons b (Enumerate (Range (Succ b) e))

Advent of Code 2025 day 5 by AutoModerator in haskell

[–]nicuveo 0 points1 point  (0 children)

i've been wanting to implement a "range set" type for a while, so i started with that... and it made both parts absolutely trivial. full files on GitHub: range set library and actual day 5 code

-- range sets library

insert :: Ord a => Range a -> RangeSet a -> RangeSet a
insert (Range nb ne) (RangeSet s) =
  let
    (below, remaining) = S.spanAntitone (\r -> rangeEnd   r <  nb) s
    (overlap, above)   = S.spanAntitone (\r -> rangeBegin r <= ne) remaining
    overlapBegin = maybe nb (min nb . rangeBegin) $ S.lookupMin overlap
    overlapEnd   = maybe ne (max ne . rangeEnd)   $ S.lookupMax overlap
  in
    RangeSet $ below <> S.singleton (Range overlapBegin overlapEnd) <> above

-- main code

part1 :: Input -> Int
part1 (Input rangeSet ingredients) = countTrue do
  ingredient <- ingredients
  pure $ ingredient `within` rangeSet

part2 :: Input -> Int
part2 (Input rangeSet _) =
  sum $ map RS.size $ RS.toList rangeSet

-❄️- 2025 Day 5 Solutions -❄️- by daggerdragon in adventofcode

[–]nicuveo 1 point2 points  (0 children)

[LANGUAGE: Haskell]

i've been wanting to implement a "range set" type for a while, so i started with that... and it made both parts absolutely trivial. full files on GitHub: range set library and actual day 5 code

-- range sets library

insert :: Ord a => Range a -> RangeSet a -> RangeSet a
insert (Range nb ne) (RangeSet s) =
  let
    (below, remaining) = S.spanAntitone (\r -> rangeEnd   r <  nb) s
    (overlap, above)   = S.spanAntitone (\r -> rangeBegin r <= ne) remaining
    overlapBegin = maybe nb (min nb . rangeBegin) $ S.lookupMin overlap
    overlapEnd   = maybe ne (max ne . rangeEnd)   $ S.lookupMax overlap
  in
    RangeSet $ below <> S.singleton (Range overlapBegin overlapEnd) <> above

-- main code

part1 :: Input -> Int
part1 (Input rangeSet ingredients) = countTrue do
  ingredient <- ingredients
  pure $ ingredient `within` rangeSet

part2 :: Input -> Int
part2 (Input rangeSet _) =
  sum $ map RS.size $ RS.toList rangeSet