Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

The taste of F#

1,185 views

Published on

Walk through a solution to Advent of Code 2016 Day 8 problem, done in F# with immutable data structures and pure functions

Published in: Software
  • Be the first to comment

  • Be the first to like this

The taste of F#

  1. 1. THE TASTE OF F#I am still Mikhail Shilkov You can nd me at @MikhailShilkov and http://mikhail.io
  2. 2. FACTS ABOUT F# .NET language Functional First Open Source
  3. 3.   0 1 2 3 4 5 6 7 8 9 x  0   # # # #  1   #         # #    2   # # #   # # # #  3   #         # #           4   #   y
  4. 4. // rect AxB   //  // turns on all of the pixels in a rectangle   // at the top‐left which is A wide and B tall  //  // e.g. rect 3x2:   0 1 2 3 4 5 6 7 8 9 x  0  1         2              3                    4   y   0 1 2 3 4 5 6 7 8 9 x  0 # # #  1 # # #      2              3                    4   y
  5. 5. // rotate row y=A by B   //  // shifts (with cycle) all of the pixels   // in row A right by B pixels  //  // e.g. rotate row y=1 by 2   0 1 2 3 4 5 6 7 8 9 x  0 # # #  1 # # #      2              3                    4   y   0 1 2 3 4 5 6 7 8 9 x  0 # # #  1     # # #      2              3                    4   y
  6. 6. // rotate column x=A by B   //  // shifts (with cycle) all of the pixels   // in column A down by B pixels  //  // e.g. rotate column x=2 by 4   0 1 2 3 4 5 6 7 8 9 x  0 # # #  1     # # #      2              3                    4   y   0 1 2 3 4 5 6 7 8 9 x  0 # # #  1       # #      2              3                    4     #  y
  7. 7. rect 1x1  rotate row y=0 by 5  rect 1x1  rotate row y=0 by 6  rect 1x1  rotate row y=0 by 5  rect 1x1  rotate row y=0 by 2  rect 1x1  rotate row y=0 by 5  rect 2x1  rotate row y=0 by 2  rect 1x1  ...
  8. 8. let Width = 10   // val Width : int = 10    let Height = 5   // val Height : int = 5
  9. 9. type Pixel = int * int    let pixel = (5, 2)   // val pixel : int * int = (5, 2)   0 1 2 3 4 5 6 7 8 9 x  0   1   2           #  3   4   y
  10. 10. type Screen = Set<Pixel>    let screen = set [ (2, 1); (5, 2); (8, 3) ]  // val screen : Set<int * int> = set [(2, 1); ...]   0 1 2 3 4 5 6 7 8 9 x  0  1     #   2           #  3                 #  4   y
  11. 11. Set.empty  Set.add element set  Set.filter predicate set  Set.union set1 set2  Set.map f set
  12. 12. let emptyScreen = Set.empty    let fullScreen =     seq { for x in 0..Width‐1 do           for y in 0..Height‐1 ‐> x, y }    |> Set.ofSeq   0 1 2 3 4 5 6 7 8 9 x  0  1         2              3                    4   y   0 1 2 3 4 5 6 7 8 9 x  0 # # # # # # # # # #  1 # # # # # # # # # #  2 # # # # # # # # # #  3 # # # # # # # # # #  4 # # # # # # # # # #  y
  13. 13. let turnOnOne (x, y) screen =    Set.add (x, y) screen    // val turnOnOne :  //  x:'a * y:'b ‐> screen:Set<'a * 'b> ‐> Set<'a * 'b>  //    when 'a : comparison and 'b : comparison    let screen2 = turnOnOne (1, 4) screen   0 1 2 3 4 5 6 7 8 9 x  0  1     #   2           #  3                 #  4   y   0 1 2 3 4 5 6 7 8 9 x  0  1     #   2           #  3                 #  4   #  y
  14. 14. let turnOn predicate screen =    let filtered = Set.filter predicate fullScreen    Set.union screen filtered    // val turnOn : f:(int * int ‐> bool) ‐>  // screen:Set<int * int> ‐> Set<int * int>
  15. 15. let turnOn predicate screen =    fullScreen    |> Set.filter predicate    |> Set.union screen    // val turnOn : f:(int * int ‐> bool) ‐>  // screen:Set<int * int> ‐> Set<int * int>
  16. 16. let turnOnRect (xmin, ymin) (xmax, ymax) screen =    let isInRect (x, y) =       x >= xmin && x <= xmax       && y >= ymin && y <= ymax    turnOn isInRect screen    // val turnOnRect :  //  xmin:int * ymin:int ‐> xmax:int * ymax:int ‐>  //    screen:Set<int * int> ‐> Set<int * int>
  17. 17. let screen3 = turnOnRect (2, 1) (3, 4) screen2    // val screen3 : Set<int * int> = set [ ... ]   0 1 2 3 4 5 6 7 8 9 x  0  1     #   2           #  3                 #  4   #  y   0 1 2 3 4 5 6 7 8 9 x  0  1     # #  2     # #   #  3     # #         #  4   # # #  y
  18. 18. let move f screen =    Set.map f screen    // val move :  //  f:('a ‐> 'b) ‐> screen:Set<'a> ‐> Set<'b>  //    when 'a : comparison and 'b : comparison
  19. 19. let rotateRow index by screen =    let mapAt (x, y) =      if y = index then (x + by) % Width, y       else x, y      move mapAt screen    // val rotateRow :  //   index:'a ‐> by:int ‐>   //     screen:Set<int * 'a> ‐> Set<int * 'a>  //       when 'a : comparison
  20. 20. let screen4 = rotateRow 3 2 screen3    // val screen4 : Set<int * int> = set [ ... ]   0 1 2 3 4 5 6 7 8 9 x  0  1     # #  2     # #   #  3     # #         #  4   # # #  y   0 1 2 3 4 5 6 7 8 9 x  0  1     # #  2     # #   #  3 #       # #          4   # # #  y
  21. 21. let rotateColumn index by screen =    let mapAt (x, y) =      if x = index then x, (y + by) % Height       else x, y      move mapAt screen    // val rotateColumn :  //   index:'a ‐> by:int ‐>   //     screen:Set<int * 'a> ‐> Set<int * 'a>  //       when 'a : comparison  
  22. 22. type Instruction =    | Rect of width: int * height: int    | RotateRow of index: int * by: int    | RotateColumn of index: int * by: int
  23. 23. let execute screen instruction =     match instruction with    | Rect (w, h) ‐> turnOnRect (0, 0) (w‐1, h‐1) screen    | RotateRow (i, by) ‐> rotateRow i by screen    | RotateColumn (i, by) ‐> rotateColumn i by screen   // val execute :  //   screen:Set<int * int> ‐> instruction:Instruction   //   ‐> Set<int * int>
  24. 24. let rec step screen instructions =    match instructions with    | [] ‐> screen    | instruction :: others ‐>       let newScreen = execute screen instruction      step newScreen others    let solve1 instructions =     step Set.empty instructions
  25. 25. let solve2 instructions =   List.fold execute Set.empty instructions
  26. 26. DEMO
  27. 27. WHAT WE SAW Strong types, cheap to create Low overhead, no boilerplate Reusable patterns and data structures "The pit of functional success"
  28. 28. THANKS!Mikhail Shilkov You can nd me at @MikhailShilkov and http://mikhail.io

×