Advent of Code 2018 day 1 part 2: find the first aggregated number that occures twice











up vote
2
down vote

favorite
1












I am using the coding puzzels of https://adventofcode.com for improving my F# skills.



Problem:



Day 1 Part 2:



Starting with frequency 0, a list of numbers should be added successive generating new frequencies. Searched is the first frequency which occurs twice. If the end of the list has been reached without success; the list should be processed again.




Example Input: [+1, -2, +3, +1]




  • Current frequency 0, change of +1; resulting frequency 1.

  • Current frequency 1, change of -2; resulting frequency -1.
    C* urrent frequency -1, change of +3; resulting frequency 2.

  • Current frequency 2, change of +1; resulting frequency 3.
    (At this point, we continue 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.




Solution



let input = [1;-2;3;1]

type State =
| FinalState of int
| IntermediateState of int * int Set

type State with
static member Zero = IntermediateState(0, Set.empty.Add(0))

let foldIntermediateState (freqHistory: int Set, freq : int) : State =
let isFinal = freqHistory |> Set.contains freq
if isFinal then
FinalState (freq)
else
IntermediateState (freq, freqHistory.Add(freq))

let foldState state value =
match state with
| FinalState _ -> state
| IntermediateState (lastFreq, freqHistory) -> foldIntermediateState (freqHistory, lastFreq + value)

let rec processListRec state lst =
let result = lst |> Seq.fold foldState state
match result with
| FinalState result -> printfn "The result is: %i" result
| IntermediateState _ -> lst |> processListRec result

input |> Seq.map int |> processListRec State.Zero


Questions



In fact, I am proud to have found a solution without mutable states that looks (at least for me) functional! :D. So any feeback that helps improving the solution or even alternative function approches for solving that problem are welcome :).










share|improve this question


























    up vote
    2
    down vote

    favorite
    1












    I am using the coding puzzels of https://adventofcode.com for improving my F# skills.



    Problem:



    Day 1 Part 2:



    Starting with frequency 0, a list of numbers should be added successive generating new frequencies. Searched is the first frequency which occurs twice. If the end of the list has been reached without success; the list should be processed again.




    Example Input: [+1, -2, +3, +1]




    • Current frequency 0, change of +1; resulting frequency 1.

    • Current frequency 1, change of -2; resulting frequency -1.
      C* urrent frequency -1, change of +3; resulting frequency 2.

    • Current frequency 2, change of +1; resulting frequency 3.
      (At this point, we continue 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.




    Solution



    let input = [1;-2;3;1]

    type State =
    | FinalState of int
    | IntermediateState of int * int Set

    type State with
    static member Zero = IntermediateState(0, Set.empty.Add(0))

    let foldIntermediateState (freqHistory: int Set, freq : int) : State =
    let isFinal = freqHistory |> Set.contains freq
    if isFinal then
    FinalState (freq)
    else
    IntermediateState (freq, freqHistory.Add(freq))

    let foldState state value =
    match state with
    | FinalState _ -> state
    | IntermediateState (lastFreq, freqHistory) -> foldIntermediateState (freqHistory, lastFreq + value)

    let rec processListRec state lst =
    let result = lst |> Seq.fold foldState state
    match result with
    | FinalState result -> printfn "The result is: %i" result
    | IntermediateState _ -> lst |> processListRec result

    input |> Seq.map int |> processListRec State.Zero


    Questions



    In fact, I am proud to have found a solution without mutable states that looks (at least for me) functional! :D. So any feeback that helps improving the solution or even alternative function approches for solving that problem are welcome :).










    share|improve this question
























      up vote
      2
      down vote

      favorite
      1









      up vote
      2
      down vote

      favorite
      1






      1





      I am using the coding puzzels of https://adventofcode.com for improving my F# skills.



      Problem:



      Day 1 Part 2:



      Starting with frequency 0, a list of numbers should be added successive generating new frequencies. Searched is the first frequency which occurs twice. If the end of the list has been reached without success; the list should be processed again.




      Example Input: [+1, -2, +3, +1]




      • Current frequency 0, change of +1; resulting frequency 1.

      • Current frequency 1, change of -2; resulting frequency -1.
        C* urrent frequency -1, change of +3; resulting frequency 2.

      • Current frequency 2, change of +1; resulting frequency 3.
        (At this point, we continue 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.




      Solution



      let input = [1;-2;3;1]

      type State =
      | FinalState of int
      | IntermediateState of int * int Set

      type State with
      static member Zero = IntermediateState(0, Set.empty.Add(0))

      let foldIntermediateState (freqHistory: int Set, freq : int) : State =
      let isFinal = freqHistory |> Set.contains freq
      if isFinal then
      FinalState (freq)
      else
      IntermediateState (freq, freqHistory.Add(freq))

      let foldState state value =
      match state with
      | FinalState _ -> state
      | IntermediateState (lastFreq, freqHistory) -> foldIntermediateState (freqHistory, lastFreq + value)

      let rec processListRec state lst =
      let result = lst |> Seq.fold foldState state
      match result with
      | FinalState result -> printfn "The result is: %i" result
      | IntermediateState _ -> lst |> processListRec result

      input |> Seq.map int |> processListRec State.Zero


      Questions



      In fact, I am proud to have found a solution without mutable states that looks (at least for me) functional! :D. So any feeback that helps improving the solution or even alternative function approches for solving that problem are welcome :).










      share|improve this question













      I am using the coding puzzels of https://adventofcode.com for improving my F# skills.



      Problem:



      Day 1 Part 2:



      Starting with frequency 0, a list of numbers should be added successive generating new frequencies. Searched is the first frequency which occurs twice. If the end of the list has been reached without success; the list should be processed again.




      Example Input: [+1, -2, +3, +1]




      • Current frequency 0, change of +1; resulting frequency 1.

      • Current frequency 1, change of -2; resulting frequency -1.
        C* urrent frequency -1, change of +3; resulting frequency 2.

      • Current frequency 2, change of +1; resulting frequency 3.
        (At this point, we continue 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.




      Solution



      let input = [1;-2;3;1]

      type State =
      | FinalState of int
      | IntermediateState of int * int Set

      type State with
      static member Zero = IntermediateState(0, Set.empty.Add(0))

      let foldIntermediateState (freqHistory: int Set, freq : int) : State =
      let isFinal = freqHistory |> Set.contains freq
      if isFinal then
      FinalState (freq)
      else
      IntermediateState (freq, freqHistory.Add(freq))

      let foldState state value =
      match state with
      | FinalState _ -> state
      | IntermediateState (lastFreq, freqHistory) -> foldIntermediateState (freqHistory, lastFreq + value)

      let rec processListRec state lst =
      let result = lst |> Seq.fold foldState state
      match result with
      | FinalState result -> printfn "The result is: %i" result
      | IntermediateState _ -> lst |> processListRec result

      input |> Seq.map int |> processListRec State.Zero


      Questions



      In fact, I am proud to have found a solution without mutable states that looks (at least for me) functional! :D. So any feeback that helps improving the solution or even alternative function approches for solving that problem are welcome :).







      programming-challenge functional-programming f#






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked yesterday









      JanDotNet

      6,6061239




      6,6061239






















          1 Answer
          1






          active

          oldest

          votes

















          up vote
          1
          down vote













          Caveat : I don't know F#.



          I liked your solution, the use of algebraic data types, pattern matching and use of list processing via fold and higher order functions are good.



          However I'm trying to apply a functional style in python (which I'm learning) and I think there is a way to do this that use simple list data structures, with (list) comprehension or the equivalent



          Here is my attempt in python to present an alternative approach



          import functools
          import itertools

          fchanges =
          with open('frequency_input') as f:
          for line in f:
          fchanges.append(int(line))

          frequencies = [sum(fchanges[:index]) for index in range(1, len(fchanges)+1)]
          skew = frequencies[-1]

          print('Skew is ' + str(skew))
          accumulator = itertools.accumulate(itertools.cycle(fchanges))
          prefix = itertools.takewhile(lambda x: (x + skew) not in frequencies, accumulator)

          # takewhile consumes the value I'm looking for to check the predicate, hence this hack
          # don't need the list, memory optimization - just need the length
          plen = functools.reduce(lambda x, y: x+1, prefix, 0)
          accumulator = itertools.accumulate(itertools.cycle(fchanges))
          print('found first repetition ' + str(next(itertools.islice(accumulator, plen, None)) + skew))


          Happy to receive feedback on my attempt too for any observers.






          share|improve this answer





















            Your Answer





            StackExchange.ifUsing("editor", function () {
            return StackExchange.using("mathjaxEditing", function () {
            StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
            StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
            });
            });
            }, "mathjax-editing");

            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "196"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            convertImagesToLinks: false,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: null,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f208866%2fadvent-of-code-2018-day-1-part-2-find-the-first-aggregated-number-that-occures%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            1 Answer
            1






            active

            oldest

            votes








            1 Answer
            1






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes








            up vote
            1
            down vote













            Caveat : I don't know F#.



            I liked your solution, the use of algebraic data types, pattern matching and use of list processing via fold and higher order functions are good.



            However I'm trying to apply a functional style in python (which I'm learning) and I think there is a way to do this that use simple list data structures, with (list) comprehension or the equivalent



            Here is my attempt in python to present an alternative approach



            import functools
            import itertools

            fchanges =
            with open('frequency_input') as f:
            for line in f:
            fchanges.append(int(line))

            frequencies = [sum(fchanges[:index]) for index in range(1, len(fchanges)+1)]
            skew = frequencies[-1]

            print('Skew is ' + str(skew))
            accumulator = itertools.accumulate(itertools.cycle(fchanges))
            prefix = itertools.takewhile(lambda x: (x + skew) not in frequencies, accumulator)

            # takewhile consumes the value I'm looking for to check the predicate, hence this hack
            # don't need the list, memory optimization - just need the length
            plen = functools.reduce(lambda x, y: x+1, prefix, 0)
            accumulator = itertools.accumulate(itertools.cycle(fchanges))
            print('found first repetition ' + str(next(itertools.islice(accumulator, plen, None)) + skew))


            Happy to receive feedback on my attempt too for any observers.






            share|improve this answer

























              up vote
              1
              down vote













              Caveat : I don't know F#.



              I liked your solution, the use of algebraic data types, pattern matching and use of list processing via fold and higher order functions are good.



              However I'm trying to apply a functional style in python (which I'm learning) and I think there is a way to do this that use simple list data structures, with (list) comprehension or the equivalent



              Here is my attempt in python to present an alternative approach



              import functools
              import itertools

              fchanges =
              with open('frequency_input') as f:
              for line in f:
              fchanges.append(int(line))

              frequencies = [sum(fchanges[:index]) for index in range(1, len(fchanges)+1)]
              skew = frequencies[-1]

              print('Skew is ' + str(skew))
              accumulator = itertools.accumulate(itertools.cycle(fchanges))
              prefix = itertools.takewhile(lambda x: (x + skew) not in frequencies, accumulator)

              # takewhile consumes the value I'm looking for to check the predicate, hence this hack
              # don't need the list, memory optimization - just need the length
              plen = functools.reduce(lambda x, y: x+1, prefix, 0)
              accumulator = itertools.accumulate(itertools.cycle(fchanges))
              print('found first repetition ' + str(next(itertools.islice(accumulator, plen, None)) + skew))


              Happy to receive feedback on my attempt too for any observers.






              share|improve this answer























                up vote
                1
                down vote










                up vote
                1
                down vote









                Caveat : I don't know F#.



                I liked your solution, the use of algebraic data types, pattern matching and use of list processing via fold and higher order functions are good.



                However I'm trying to apply a functional style in python (which I'm learning) and I think there is a way to do this that use simple list data structures, with (list) comprehension or the equivalent



                Here is my attempt in python to present an alternative approach



                import functools
                import itertools

                fchanges =
                with open('frequency_input') as f:
                for line in f:
                fchanges.append(int(line))

                frequencies = [sum(fchanges[:index]) for index in range(1, len(fchanges)+1)]
                skew = frequencies[-1]

                print('Skew is ' + str(skew))
                accumulator = itertools.accumulate(itertools.cycle(fchanges))
                prefix = itertools.takewhile(lambda x: (x + skew) not in frequencies, accumulator)

                # takewhile consumes the value I'm looking for to check the predicate, hence this hack
                # don't need the list, memory optimization - just need the length
                plen = functools.reduce(lambda x, y: x+1, prefix, 0)
                accumulator = itertools.accumulate(itertools.cycle(fchanges))
                print('found first repetition ' + str(next(itertools.islice(accumulator, plen, None)) + skew))


                Happy to receive feedback on my attempt too for any observers.






                share|improve this answer












                Caveat : I don't know F#.



                I liked your solution, the use of algebraic data types, pattern matching and use of list processing via fold and higher order functions are good.



                However I'm trying to apply a functional style in python (which I'm learning) and I think there is a way to do this that use simple list data structures, with (list) comprehension or the equivalent



                Here is my attempt in python to present an alternative approach



                import functools
                import itertools

                fchanges =
                with open('frequency_input') as f:
                for line in f:
                fchanges.append(int(line))

                frequencies = [sum(fchanges[:index]) for index in range(1, len(fchanges)+1)]
                skew = frequencies[-1]

                print('Skew is ' + str(skew))
                accumulator = itertools.accumulate(itertools.cycle(fchanges))
                prefix = itertools.takewhile(lambda x: (x + skew) not in frequencies, accumulator)

                # takewhile consumes the value I'm looking for to check the predicate, hence this hack
                # don't need the list, memory optimization - just need the length
                plen = functools.reduce(lambda x, y: x+1, prefix, 0)
                accumulator = itertools.accumulate(itertools.cycle(fchanges))
                print('found first repetition ' + str(next(itertools.islice(accumulator, plen, None)) + skew))


                Happy to receive feedback on my attempt too for any observers.







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered yesterday









                Bhaskar

                27112




                27112






























                    draft saved

                    draft discarded




















































                    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.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f208866%2fadvent-of-code-2018-day-1-part-2-find-the-first-aggregated-number-that-occures%23new-answer', 'question_page');
                    }
                    );

                    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







                    Popular posts from this blog

                    Quarter-circle Tiles

                    build a pushdown automaton that recognizes the reverse language of a given pushdown automaton?

                    Mont Emei