Find the length of a frequency-change cycle (Advent of Code 2018)
up vote
3
down vote
favorite
I tried to do the second part of the 1. December challenge of Advent of Code in Haskell. I'm fairly new to Haskell but I have plenty of experience in other (procedural) languages. I struggled with the challenge for hours because the program would hang and it wouldn't produce any output although I couldn't find a problem in my code. Eventually it turned out that my programm worked correctly but it just took very long. To be exact the program took 2 minutes and 40 seconds. According to Advent of Code every challenge should able to execute within 15 seconds though.
So what makes my code so slow?
The task:
You notice that the device repeats the same frequency change list over and over. To calibrate the device, you need to find the first frequency it reaches twice.
For example, using the same list of changes above, the device would
loop as follows:
Current frequency 0, change of +1; resulting frequency 1.
Current frequency 1, change of -2; resulting frequency -1.
Current frequency -1, change of +3; resulting frequency 2.
Current frequency 2, change of +1; resulting frequency 3.
(At this point, the device continues from the start of the list.)
Current frequency 3, change of +1; resulting frequency 4.
Current frequency 4, change of -2; resulting frequency 2, which has already been seen.
In this example, the first frequency reached twice is 2. Note that
your device might need to repeat its list of frequency changes many
times before a duplicate frequency is found, and that duplicates might
be found while in the middle of processing the list.
Here are other examples:
+1, -1 first reaches 0 twice.
+3, +3, +4, -2, -4 first reaches 10 twice.
-6, +3, +8, +5, -6 first reaches 5 twice.
+7, +7, -2, -7, -4 first reaches 14 twice.
What is the first frequency your device reaches twice?
My code:
module DayOnePartTwo where
import System.IO
import Data.Maybe
inputFileName = "input.txt"
input :: String -> [Integer]
input contents = toNum (cleanNumbers (splitNumbers contents))
where
cleanNumbers strs = map removeLeadingPlus strs
splitNumbers string = words string
toNum numbers = map read numbers
removeLeadingPlus str = if str !! 0 == '+' then tail str else str
accumulate :: [Integer] -> [Integer]
accumulate list = accumulator list 0
where
accumulator :: Num a => [a] -> a -> [a]
accumulator (x:xs) state = (x + state) : accumulator xs (x + state)
accumulator state =
duplicate :: [Integer] -> Maybe Integer
duplicate list = dup list [0]
where
dup (x:xs) visited =
if elem x visited
then Just x
else dup xs (x:visited)
dup _ = Nothing
firstCyclicDuplicate :: [Integer] -> Maybe Integer
firstCyclicDuplicate list = duplicate (accumulate cycledList)
where
cycledList = cycle list
main :: IO ()
main = do
contents <- readFile inputFileName
case (firstCyclicDuplicate (input contents)) of
Just a -> print (show a)
Nothing -> print "There is no first duplicate"
This seems to be related to slow advent of code 2018 day 1 part 2 solution in haskell although my algorithm is different.
beginner programming-challenge haskell time-limit-exceeded
New contributor
add a comment |
up vote
3
down vote
favorite
I tried to do the second part of the 1. December challenge of Advent of Code in Haskell. I'm fairly new to Haskell but I have plenty of experience in other (procedural) languages. I struggled with the challenge for hours because the program would hang and it wouldn't produce any output although I couldn't find a problem in my code. Eventually it turned out that my programm worked correctly but it just took very long. To be exact the program took 2 minutes and 40 seconds. According to Advent of Code every challenge should able to execute within 15 seconds though.
So what makes my code so slow?
The task:
You notice that the device repeats the same frequency change list over and over. To calibrate the device, you need to find the first frequency it reaches twice.
For example, using the same list of changes above, the device would
loop as follows:
Current frequency 0, change of +1; resulting frequency 1.
Current frequency 1, change of -2; resulting frequency -1.
Current frequency -1, change of +3; resulting frequency 2.
Current frequency 2, change of +1; resulting frequency 3.
(At this point, the device continues from the start of the list.)
Current frequency 3, change of +1; resulting frequency 4.
Current frequency 4, change of -2; resulting frequency 2, which has already been seen.
In this example, the first frequency reached twice is 2. Note that
your device might need to repeat its list of frequency changes many
times before a duplicate frequency is found, and that duplicates might
be found while in the middle of processing the list.
Here are other examples:
+1, -1 first reaches 0 twice.
+3, +3, +4, -2, -4 first reaches 10 twice.
-6, +3, +8, +5, -6 first reaches 5 twice.
+7, +7, -2, -7, -4 first reaches 14 twice.
What is the first frequency your device reaches twice?
My code:
module DayOnePartTwo where
import System.IO
import Data.Maybe
inputFileName = "input.txt"
input :: String -> [Integer]
input contents = toNum (cleanNumbers (splitNumbers contents))
where
cleanNumbers strs = map removeLeadingPlus strs
splitNumbers string = words string
toNum numbers = map read numbers
removeLeadingPlus str = if str !! 0 == '+' then tail str else str
accumulate :: [Integer] -> [Integer]
accumulate list = accumulator list 0
where
accumulator :: Num a => [a] -> a -> [a]
accumulator (x:xs) state = (x + state) : accumulator xs (x + state)
accumulator state =
duplicate :: [Integer] -> Maybe Integer
duplicate list = dup list [0]
where
dup (x:xs) visited =
if elem x visited
then Just x
else dup xs (x:visited)
dup _ = Nothing
firstCyclicDuplicate :: [Integer] -> Maybe Integer
firstCyclicDuplicate list = duplicate (accumulate cycledList)
where
cycledList = cycle list
main :: IO ()
main = do
contents <- readFile inputFileName
case (firstCyclicDuplicate (input contents)) of
Just a -> print (show a)
Nothing -> print "There is no first duplicate"
This seems to be related to slow advent of code 2018 day 1 part 2 solution in haskell although my algorithm is different.
beginner programming-challenge haskell time-limit-exceeded
New contributor
add a comment |
up vote
3
down vote
favorite
up vote
3
down vote
favorite
I tried to do the second part of the 1. December challenge of Advent of Code in Haskell. I'm fairly new to Haskell but I have plenty of experience in other (procedural) languages. I struggled with the challenge for hours because the program would hang and it wouldn't produce any output although I couldn't find a problem in my code. Eventually it turned out that my programm worked correctly but it just took very long. To be exact the program took 2 minutes and 40 seconds. According to Advent of Code every challenge should able to execute within 15 seconds though.
So what makes my code so slow?
The task:
You notice that the device repeats the same frequency change list over and over. To calibrate the device, you need to find the first frequency it reaches twice.
For example, using the same list of changes above, the device would
loop as follows:
Current frequency 0, change of +1; resulting frequency 1.
Current frequency 1, change of -2; resulting frequency -1.
Current frequency -1, change of +3; resulting frequency 2.
Current frequency 2, change of +1; resulting frequency 3.
(At this point, the device continues from the start of the list.)
Current frequency 3, change of +1; resulting frequency 4.
Current frequency 4, change of -2; resulting frequency 2, which has already been seen.
In this example, the first frequency reached twice is 2. Note that
your device might need to repeat its list of frequency changes many
times before a duplicate frequency is found, and that duplicates might
be found while in the middle of processing the list.
Here are other examples:
+1, -1 first reaches 0 twice.
+3, +3, +4, -2, -4 first reaches 10 twice.
-6, +3, +8, +5, -6 first reaches 5 twice.
+7, +7, -2, -7, -4 first reaches 14 twice.
What is the first frequency your device reaches twice?
My code:
module DayOnePartTwo where
import System.IO
import Data.Maybe
inputFileName = "input.txt"
input :: String -> [Integer]
input contents = toNum (cleanNumbers (splitNumbers contents))
where
cleanNumbers strs = map removeLeadingPlus strs
splitNumbers string = words string
toNum numbers = map read numbers
removeLeadingPlus str = if str !! 0 == '+' then tail str else str
accumulate :: [Integer] -> [Integer]
accumulate list = accumulator list 0
where
accumulator :: Num a => [a] -> a -> [a]
accumulator (x:xs) state = (x + state) : accumulator xs (x + state)
accumulator state =
duplicate :: [Integer] -> Maybe Integer
duplicate list = dup list [0]
where
dup (x:xs) visited =
if elem x visited
then Just x
else dup xs (x:visited)
dup _ = Nothing
firstCyclicDuplicate :: [Integer] -> Maybe Integer
firstCyclicDuplicate list = duplicate (accumulate cycledList)
where
cycledList = cycle list
main :: IO ()
main = do
contents <- readFile inputFileName
case (firstCyclicDuplicate (input contents)) of
Just a -> print (show a)
Nothing -> print "There is no first duplicate"
This seems to be related to slow advent of code 2018 day 1 part 2 solution in haskell although my algorithm is different.
beginner programming-challenge haskell time-limit-exceeded
New contributor
I tried to do the second part of the 1. December challenge of Advent of Code in Haskell. I'm fairly new to Haskell but I have plenty of experience in other (procedural) languages. I struggled with the challenge for hours because the program would hang and it wouldn't produce any output although I couldn't find a problem in my code. Eventually it turned out that my programm worked correctly but it just took very long. To be exact the program took 2 minutes and 40 seconds. According to Advent of Code every challenge should able to execute within 15 seconds though.
So what makes my code so slow?
The task:
You notice that the device repeats the same frequency change list over and over. To calibrate the device, you need to find the first frequency it reaches twice.
For example, using the same list of changes above, the device would
loop as follows:
Current frequency 0, change of +1; resulting frequency 1.
Current frequency 1, change of -2; resulting frequency -1.
Current frequency -1, change of +3; resulting frequency 2.
Current frequency 2, change of +1; resulting frequency 3.
(At this point, the device continues from the start of the list.)
Current frequency 3, change of +1; resulting frequency 4.
Current frequency 4, change of -2; resulting frequency 2, which has already been seen.
In this example, the first frequency reached twice is 2. Note that
your device might need to repeat its list of frequency changes many
times before a duplicate frequency is found, and that duplicates might
be found while in the middle of processing the list.
Here are other examples:
+1, -1 first reaches 0 twice.
+3, +3, +4, -2, -4 first reaches 10 twice.
-6, +3, +8, +5, -6 first reaches 5 twice.
+7, +7, -2, -7, -4 first reaches 14 twice.
What is the first frequency your device reaches twice?
My code:
module DayOnePartTwo where
import System.IO
import Data.Maybe
inputFileName = "input.txt"
input :: String -> [Integer]
input contents = toNum (cleanNumbers (splitNumbers contents))
where
cleanNumbers strs = map removeLeadingPlus strs
splitNumbers string = words string
toNum numbers = map read numbers
removeLeadingPlus str = if str !! 0 == '+' then tail str else str
accumulate :: [Integer] -> [Integer]
accumulate list = accumulator list 0
where
accumulator :: Num a => [a] -> a -> [a]
accumulator (x:xs) state = (x + state) : accumulator xs (x + state)
accumulator state =
duplicate :: [Integer] -> Maybe Integer
duplicate list = dup list [0]
where
dup (x:xs) visited =
if elem x visited
then Just x
else dup xs (x:visited)
dup _ = Nothing
firstCyclicDuplicate :: [Integer] -> Maybe Integer
firstCyclicDuplicate list = duplicate (accumulate cycledList)
where
cycledList = cycle list
main :: IO ()
main = do
contents <- readFile inputFileName
case (firstCyclicDuplicate (input contents)) of
Just a -> print (show a)
Nothing -> print "There is no first duplicate"
This seems to be related to slow advent of code 2018 day 1 part 2 solution in haskell although my algorithm is different.
beginner programming-challenge haskell time-limit-exceeded
beginner programming-challenge haskell time-limit-exceeded
New contributor
New contributor
edited 16 mins ago
200_success
127k15148412
127k15148412
New contributor
asked 5 hours ago
Aaronmacaron
161
161
New contributor
New contributor
add a comment |
add a comment |
active
oldest
votes
active
oldest
votes
active
oldest
votes
active
oldest
votes
active
oldest
votes
Aaronmacaron is a new contributor. Be nice, and check out our Code of Conduct.
Aaronmacaron is a new contributor. Be nice, and check out our Code of Conduct.
Aaronmacaron is a new contributor. Be nice, and check out our Code of Conduct.
Aaronmacaron is a new contributor. Be nice, and check out our Code of Conduct.
Thanks for contributing an answer to Code Review Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f208844%2ffind-the-length-of-a-frequency-change-cycle-advent-of-code-2018%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown