First see the problem solved using the List monad and a Scala for comprehension.
Then see the Scala program translated into Haskell, both using a do expressions and using a List comprehension.
Understand how the Scala for comprehension is desugared, and what role the withFilter function plays.
Also understand how the Haskell do expressions and List comprehension are desugared, and what role the guard function plays.
Scala code for Part 1: https://github.com/philipschwarz/n-queens-combinatorial-problem-scala-part-1
Errata: on slide 30, the resulting lists should be Haskell ones rather than Scala ones.
Left and Right Folds- Comparison of a mathematical definition and a programm...Philip Schwarz
We compare typical definitions of the left and right fold functions, with their mathematical definitions in Sergei Winitzki’s upcoming book: The Science of Functional Programming.
Errata:
Slide 13: "The way 𝑓𝑜𝑙𝑑𝑙 does it is by associating to the right" - should, of course ,end in "to the left".
‘go-to’ general-purpose sequential collections -from Java To ScalaPhilip Schwarz
The simple idea of this slide deck is that it collects in a single place quite a bit of information that can be used to gain a basic understanding of some key differences between the ’goto’ sequential collections of Java and Scala.
Errata:
* the twitter handle of Daniel Westheide is @kaffeecoder and not @cafeecoder
* on slide 35, the numbers 215, 220, 225 and 230, should be 2^15, 2^20, 2^25 and 2^30 respectively
* on slide 54, the bottom left node should be green rather than black
Refactoring: A First Example - Martin Fowler’s First Example of Refactoring, ...Philip Schwarz
Follow in the footsteps of refactoring guru Martin Fowler as he improves the design of a program in a simple yet instructive refactoring example whose JavaScript code and associated refactoring is herein adapted to Scala.
Based on the second edition of ‘the’ Refactoring book.
Here is a github repository with the whole refactoring, from start to finish, following the steps seen in the slides https://github.com/philipschwarz/refactoring-a-first-example-scala
Sum and Product Types -The Fruit Salad & Fruit Snack Example - From F# to Ha...Philip Schwarz
- The document describes how product types (built using AND) and sum types (built using OR) are used to define types for representing fruit salads and fruit snacks in F#, Haskell, Scala, and Java.
- Product types combine elements and are used to define the FruitSalad type, while sum types allow alternatives and are used to define the FruitSnack type consisting of different fruits.
- Pattern matching is demonstrated to write functions that analyze and return different strings based on the values of FruitSalad and FruitSnack types.
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1Philip Schwarz
slides can look grainy and/or out of focus when seen on slideshare - download for flawless quality - Based on Scott Wlaschin’s great book 'Domain Modeling Made Functional' and on Martin Odersky's talk 'A Tour of Scala 3'.
Left and Right Folds- Comparison of a mathematical definition and a programm...Philip Schwarz
We compare typical definitions of the left and right fold functions, with their mathematical definitions in Sergei Winitzki’s upcoming book: The Science of Functional Programming.
Errata:
Slide 13: "The way 𝑓𝑜𝑙𝑑𝑙 does it is by associating to the right" - should, of course ,end in "to the left".
‘go-to’ general-purpose sequential collections -from Java To ScalaPhilip Schwarz
The simple idea of this slide deck is that it collects in a single place quite a bit of information that can be used to gain a basic understanding of some key differences between the ’goto’ sequential collections of Java and Scala.
Errata:
* the twitter handle of Daniel Westheide is @kaffeecoder and not @cafeecoder
* on slide 35, the numbers 215, 220, 225 and 230, should be 2^15, 2^20, 2^25 and 2^30 respectively
* on slide 54, the bottom left node should be green rather than black
Refactoring: A First Example - Martin Fowler’s First Example of Refactoring, ...Philip Schwarz
Follow in the footsteps of refactoring guru Martin Fowler as he improves the design of a program in a simple yet instructive refactoring example whose JavaScript code and associated refactoring is herein adapted to Scala.
Based on the second edition of ‘the’ Refactoring book.
Here is a github repository with the whole refactoring, from start to finish, following the steps seen in the slides https://github.com/philipschwarz/refactoring-a-first-example-scala
Sum and Product Types -The Fruit Salad & Fruit Snack Example - From F# to Ha...Philip Schwarz
- The document describes how product types (built using AND) and sum types (built using OR) are used to define types for representing fruit salads and fruit snacks in F#, Haskell, Scala, and Java.
- Product types combine elements and are used to define the FruitSalad type, while sum types allow alternatives and are used to define the FruitSnack type consisting of different fruits.
- Pattern matching is demonstrated to write functions that analyze and return different strings based on the values of FruitSalad and FruitSnack types.
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1Philip Schwarz
slides can look grainy and/or out of focus when seen on slideshare - download for flawless quality - Based on Scott Wlaschin’s great book 'Domain Modeling Made Functional' and on Martin Odersky's talk 'A Tour of Scala 3'.
Nat, List and Option Monoids -from scratch -Combining and Folding -an examplePhilip Schwarz
Nat, List and Option Monoids, from scratch. Combining and Folding: an example.
Code: https://github.com/philipschwarz/nat-list-and-option-monoids-from-scratch-combining-and-folding-an-example
The document discusses the Uniform Access Principle, which states that all services offered by a module should be available through a uniform notation that does not reveal whether they are implemented through storage or computation. It provides examples of how different languages do or do not follow this principle, and explains that following this principle helps avoid breaking client code when implementation details change. It also discusses how Scala supports the Uniform Access Principle for parameterless methods.
ZIO-Direct allows direct style programming with ZIO. This library provides a *syntactic sugar* that is more powerful than for-comprehensions as well as more natural to use. Simply add the `.run` suffix to any ZIO effect in order to retrieve it's value.
download for better quality - Learn how to use an Applicative Functor to handle multiple independent effectful values through the work of Sergei Winitzki, Runar Bjarnason, Paul Chiusano, Debasish Ghosh and Adelbert Chang
(video and more at http://fsharpforfunandprofit.com/fppatterns)
In object-oriented development, we are all familiar with design patterns such as the Strategy pattern and Decorator pattern, and design principles such as SOLID. The functional programming community has design patterns and principles as well. This talk will provide an overview of some of these patterns (such as currying, monads), and present some demonstrations of FP design in practice. We'll also look at some of the ways you can use these patterns as part of a domain driven design process, with some simple real world examples in F#. No jargon, no maths, and no prior F# experience necessary.
Arriving at monads by going from pure-function composition to effectful-funct...Philip Schwarz
This document discusses functional programming principles and how to deal with effects like mutability, exceptions, and logging in a pure functional style. It introduces the idea of effects, distinguishing them from side effects. Six common effects are discussed: partiality, nondeterminism, dependency injection, logging, mutability, and exceptions. The document explains how the Kleisli category and monads can be used to define functions with effects and allow their composition while preserving referential transparency. This provides techniques for handling effects normally found in imperative programs using functional programming.
The Functional Programming Triad of Folding, Scanning and Iteration - a first...Philip Schwarz
This slide deck can work both as an aide mémoire (memory jogger), or as a first (not completely trivial) example of using left folds, left scans and iteration, to implement mathematical induction.
Errata: on almost half of the slides there is some minor typo or imperfection or in some cases a minor error and in one case, an omission. See a later version for corrections and some improvements.
(for best quality images, either download or view here: https://philipschwarz.dev/fpilluminated/?page_id=455)
Scala code for latest version: https://github.com/philipschwarz/fp-fold-scan-iterate-triad-a-first-example-scala
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - with ...Philip Schwarz
(download for perfect quality) - See how recursive functions and structural induction relate to recursive datatypes.
Follow along as the fold abstraction is introduced and explained.
Watch as folding is used to simplify the definition of recursive functions over recursive datatypes
Part 1 - through the work of Richard Bird and Graham Hutton.
This version corrects the following issues:
slide 7, 11 fib(0) is 0,rather than 1
slide 23: was supposed to be followed by 2-3 slides recapitulating definitions of factorial and fibonacci with and without foldr, plus translation to scala
slide 36: concat not invoked in concat example
slides 48 and 49: unwanted 'm' in definition of sum
throughout: a couple of typographical errors
throughout: several aesthetic imperfections (wrong font, wrong font colour)
download for better quality - Learn about the sequence and traverse functions
through the work of Runar Bjarnason and Paul Chiusano, authors of Functional Programming in Scala https://www.manning.com/books/functional-programming-in-scala, and others (Martin Odersky, Derek Wyatt, Adelbert Chang)
In this slide deck we are going to see some examples of how the effort required to read an understand the Sieve of Eratosthenes varies greatly depending on the programming paradigm used to implement the algorithm.
We'll see code in Java, Scheme, Haskell and Scala.
Errata:
slide 10: "points asserts" should be "asserts"
slide 22,23,25: "// larger than that root.private static int" should be "// larger than that root"
slide 29: "three slides" should be "two slides"
slide 45,46,48,49: List.range(m,n + 1) should be List.range(2,maxValue + 1)
Download for better quality.
Monads do not Compose. Not in a generic way - There is no general way of composing monads.
A comment from Rúnar Bjarnason, coauthor of FP in Scala: "They do compose in a different generic way. For any two monads F and G we can take the coproduct which is roughly Free of Either F or G (up to normalization)".
Another comment from Sergei Winitzki (which caused me to upload https://www.slideshare.net/pjschwarz/addendum-to-monads-do-not-compose): "It is a mistake to think that a traversable monad can be composed with another monad. It is true that, given `Traversable`, you can implement the monad's methods (pure and flatMap) for the composition with another monad (as in your slides 21 to 26), but this is a deceptive appearance. The laws of the `Traversable` typeclass are far insufficient to guarantee the laws of the resulting composed monad. The only traversable monads that work correctly are Option, Either, and Writer. It is true that you can implement the type signature of the `swap` function for any `Traversable` monad. However, the `swap` function for monads needs to satisfy very different and stronger laws than the `sequence` function from the `Traversable` type class. I'll have to look at the "Book of Monads"; but, if my memory serves, the FPiS book does not derive any of these laws." See https://www.linkedin.com/feed/update/urn:li:groupPost:41001-6523141414614814720?commentUrn=urn%3Ali%3Acomment%3A%28groupPost%3A41001-6523141414614814720%2C6532108273053761536%29
The Functional Programming Toolkit (NDC Oslo 2019)Scott Wlaschin
(slides and video at https://fsharpforfunandprofit.com/fptoolkit)
The techniques and patterns used in functional programming are very different from object-oriented programming, and when you are just starting out it can be hard to know how they all fit together.
In this big picture talk for FP beginners, I'll present some of the common tools that can be found in a functional programmer's toolbelt; tools such as "map", "apply", "bind", and "sequence". What are they? Why are they important? How are they used in practice? And how do they relate to scary sounding concepts like functors, monads, and applicatives?
Download for better quality - Learn about the composition of effectful functions through the work of Bartosz Milewski, Rob Norris, Rúnar Bjarnason and Debasish Ghosh.
This talk was presented on Aug 3rd 2023 during the Scala in the City event a ITV in London https://www.meetup.com/scala-in-the-city/events/292844968/
Visit the following for a description, slideshow, all slides with transcript, pdf, github repo, and eventually a video recording: http://fpilluminated.com/assets/n-queens-combinatorial-puzzle-meets-cats.html
At the centre of this talk is the N-Queens combinatorial puzzle. The reason why this puzzle features in the Scala book and functional programming course by Martin Odersky (the language’s creator), is that such puzzles are a particularly suitable application area of 'for comprehensions'.
We’ll start by (re)acquainting ourselves with the puzzle, and seeing the role played in it by permutations. Next, we’ll see how, when wanting to visualise candidate puzzle solutions, Cats’ monoidal functions fold and foldMap are a great fit for combining images.
While we are all very familiar with the triad providing the bread, butter and jam of functional programming, i.e. map, filter and fold, not everyone knows about the corresponding functions in Cats’ monadic variant of the triad, i.e. mapM, filterM and foldM, which we are going to learn about next.
As is often the case in functional programming, the traverse function makes an appearance, and we shall grab the opportunity to point out the symmetry that exists in the interrelation of flatMap / foldMap / traverse and flatten / fold / sequence.
Armed with an understanding of foldM, we then look at how such a function can be used to implement an iterative algorithm for the N-Queens puzzle.
The talk ends by pointing out that the iterative algorithm is smarter than the recursive one, because it ‘remembers’ where it has already placed previous queens.
download for better quality - Learn about the sequence and traverse functions
through the work of Runar Bjarnason and Paul Chiusano, authors of Functional Programming in Scala https://www.manning.com/books/functional-programming-in-scala
The Functional Programming Triad of Map, Filter and FoldPhilip Schwarz
This slide deck is my homage to SICP, the book which first introduced me to the Functional Programming triad of map, filter and fold.
It was during my Computer Science degree that a fellow student gave me a copy of the first edition, not long after the book came out.
I have not yet come across a better introduction to these three functions.
The upcoming slides are closely based on the second edition of the book, a free online copy of which can be found here:
https://mitpress.mit.edu/sites/default/files/sicp/full-text/book/book.html.
Download for original image quality.
Errata:
slide 20: the Clojure map function is in fact the Scheme one repeated - see code below for correction.
Scheme code: https://github.com/philipschwarz/the-fp-triad-of-map-filter-and-fold-scheme
Clojure code: https://github.com/philipschwarz/the-fp-triad-of-map-filter-and-fold-clojure
The document discusses object-oriented programming (OOP) and functional programming (FP). It argues that OOP and FP are not opposites and can be effectively combined. It addresses common myths about FP, such as that it is new, hard, or only suitable for mathematical problems. The document also compares how OOP and FP approach concepts like decomposition, composition, error handling, and mutability/referential transparency. While both approaches have merits, the document concludes there is no single best approach and the choice depends on the problem and programmer preferences.
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part ...Philip Schwarz
(download for best quality slides) Gain a deeper understanding of why right folds over very large and infinite lists are sometimes possible in Haskell.
See how lazy evaluation and function strictness affect left and right folds in Haskell.
Learn when an ordinary left fold results in a space leak and how to avoid it using a strict left fold.
This version eliminates some minor imperfections and corrects the following two errors:
slide 15: "as sharing is required" should be "as sharing is not required"
slide 43: 푠푓표푙푑푙 (⊕) 푎 should be 푠푓표푙푑푙 (⊕) 푒
The document describes several algorithms related to graph searching and optimization problems:
1) Binary search and depth-first search algorithms for searching arrays and graphs.
2) Breadth-first search and shortest path algorithms using BFS for graphs.
3) Topological sort and n-queens algorithms using backtracking to solve optimization problems on graphs and boards.
4) Hamiltonian cycle algorithm applying backtracking to find cycles in graphs.
The algorithms are represented using pseudocode with common structures like adjacency lists, matrices, queues, and recursion to traverse and search data structures efficiently.
The document describes several algorithms related to graph searching and optimization problems:
1) Binary search and depth-first search algorithms for searching arrays and graphs.
2) Breadth-first search for graphs and finding shortest paths.
3) Topological sorting of directed acyclic graphs.
4) Backtracking algorithms for solving the n-queens problem and searching for Hamiltonian cycles in graphs.
Nat, List and Option Monoids -from scratch -Combining and Folding -an examplePhilip Schwarz
Nat, List and Option Monoids, from scratch. Combining and Folding: an example.
Code: https://github.com/philipschwarz/nat-list-and-option-monoids-from-scratch-combining-and-folding-an-example
The document discusses the Uniform Access Principle, which states that all services offered by a module should be available through a uniform notation that does not reveal whether they are implemented through storage or computation. It provides examples of how different languages do or do not follow this principle, and explains that following this principle helps avoid breaking client code when implementation details change. It also discusses how Scala supports the Uniform Access Principle for parameterless methods.
ZIO-Direct allows direct style programming with ZIO. This library provides a *syntactic sugar* that is more powerful than for-comprehensions as well as more natural to use. Simply add the `.run` suffix to any ZIO effect in order to retrieve it's value.
download for better quality - Learn how to use an Applicative Functor to handle multiple independent effectful values through the work of Sergei Winitzki, Runar Bjarnason, Paul Chiusano, Debasish Ghosh and Adelbert Chang
(video and more at http://fsharpforfunandprofit.com/fppatterns)
In object-oriented development, we are all familiar with design patterns such as the Strategy pattern and Decorator pattern, and design principles such as SOLID. The functional programming community has design patterns and principles as well. This talk will provide an overview of some of these patterns (such as currying, monads), and present some demonstrations of FP design in practice. We'll also look at some of the ways you can use these patterns as part of a domain driven design process, with some simple real world examples in F#. No jargon, no maths, and no prior F# experience necessary.
Arriving at monads by going from pure-function composition to effectful-funct...Philip Schwarz
This document discusses functional programming principles and how to deal with effects like mutability, exceptions, and logging in a pure functional style. It introduces the idea of effects, distinguishing them from side effects. Six common effects are discussed: partiality, nondeterminism, dependency injection, logging, mutability, and exceptions. The document explains how the Kleisli category and monads can be used to define functions with effects and allow their composition while preserving referential transparency. This provides techniques for handling effects normally found in imperative programs using functional programming.
The Functional Programming Triad of Folding, Scanning and Iteration - a first...Philip Schwarz
This slide deck can work both as an aide mémoire (memory jogger), or as a first (not completely trivial) example of using left folds, left scans and iteration, to implement mathematical induction.
Errata: on almost half of the slides there is some minor typo or imperfection or in some cases a minor error and in one case, an omission. See a later version for corrections and some improvements.
(for best quality images, either download or view here: https://philipschwarz.dev/fpilluminated/?page_id=455)
Scala code for latest version: https://github.com/philipschwarz/fp-fold-scan-iterate-triad-a-first-example-scala
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - with ...Philip Schwarz
(download for perfect quality) - See how recursive functions and structural induction relate to recursive datatypes.
Follow along as the fold abstraction is introduced and explained.
Watch as folding is used to simplify the definition of recursive functions over recursive datatypes
Part 1 - through the work of Richard Bird and Graham Hutton.
This version corrects the following issues:
slide 7, 11 fib(0) is 0,rather than 1
slide 23: was supposed to be followed by 2-3 slides recapitulating definitions of factorial and fibonacci with and without foldr, plus translation to scala
slide 36: concat not invoked in concat example
slides 48 and 49: unwanted 'm' in definition of sum
throughout: a couple of typographical errors
throughout: several aesthetic imperfections (wrong font, wrong font colour)
download for better quality - Learn about the sequence and traverse functions
through the work of Runar Bjarnason and Paul Chiusano, authors of Functional Programming in Scala https://www.manning.com/books/functional-programming-in-scala, and others (Martin Odersky, Derek Wyatt, Adelbert Chang)
In this slide deck we are going to see some examples of how the effort required to read an understand the Sieve of Eratosthenes varies greatly depending on the programming paradigm used to implement the algorithm.
We'll see code in Java, Scheme, Haskell and Scala.
Errata:
slide 10: "points asserts" should be "asserts"
slide 22,23,25: "// larger than that root.private static int" should be "// larger than that root"
slide 29: "three slides" should be "two slides"
slide 45,46,48,49: List.range(m,n + 1) should be List.range(2,maxValue + 1)
Download for better quality.
Monads do not Compose. Not in a generic way - There is no general way of composing monads.
A comment from Rúnar Bjarnason, coauthor of FP in Scala: "They do compose in a different generic way. For any two monads F and G we can take the coproduct which is roughly Free of Either F or G (up to normalization)".
Another comment from Sergei Winitzki (which caused me to upload https://www.slideshare.net/pjschwarz/addendum-to-monads-do-not-compose): "It is a mistake to think that a traversable monad can be composed with another monad. It is true that, given `Traversable`, you can implement the monad's methods (pure and flatMap) for the composition with another monad (as in your slides 21 to 26), but this is a deceptive appearance. The laws of the `Traversable` typeclass are far insufficient to guarantee the laws of the resulting composed monad. The only traversable monads that work correctly are Option, Either, and Writer. It is true that you can implement the type signature of the `swap` function for any `Traversable` monad. However, the `swap` function for monads needs to satisfy very different and stronger laws than the `sequence` function from the `Traversable` type class. I'll have to look at the "Book of Monads"; but, if my memory serves, the FPiS book does not derive any of these laws." See https://www.linkedin.com/feed/update/urn:li:groupPost:41001-6523141414614814720?commentUrn=urn%3Ali%3Acomment%3A%28groupPost%3A41001-6523141414614814720%2C6532108273053761536%29
The Functional Programming Toolkit (NDC Oslo 2019)Scott Wlaschin
(slides and video at https://fsharpforfunandprofit.com/fptoolkit)
The techniques and patterns used in functional programming are very different from object-oriented programming, and when you are just starting out it can be hard to know how they all fit together.
In this big picture talk for FP beginners, I'll present some of the common tools that can be found in a functional programmer's toolbelt; tools such as "map", "apply", "bind", and "sequence". What are they? Why are they important? How are they used in practice? And how do they relate to scary sounding concepts like functors, monads, and applicatives?
Download for better quality - Learn about the composition of effectful functions through the work of Bartosz Milewski, Rob Norris, Rúnar Bjarnason and Debasish Ghosh.
This talk was presented on Aug 3rd 2023 during the Scala in the City event a ITV in London https://www.meetup.com/scala-in-the-city/events/292844968/
Visit the following for a description, slideshow, all slides with transcript, pdf, github repo, and eventually a video recording: http://fpilluminated.com/assets/n-queens-combinatorial-puzzle-meets-cats.html
At the centre of this talk is the N-Queens combinatorial puzzle. The reason why this puzzle features in the Scala book and functional programming course by Martin Odersky (the language’s creator), is that such puzzles are a particularly suitable application area of 'for comprehensions'.
We’ll start by (re)acquainting ourselves with the puzzle, and seeing the role played in it by permutations. Next, we’ll see how, when wanting to visualise candidate puzzle solutions, Cats’ monoidal functions fold and foldMap are a great fit for combining images.
While we are all very familiar with the triad providing the bread, butter and jam of functional programming, i.e. map, filter and fold, not everyone knows about the corresponding functions in Cats’ monadic variant of the triad, i.e. mapM, filterM and foldM, which we are going to learn about next.
As is often the case in functional programming, the traverse function makes an appearance, and we shall grab the opportunity to point out the symmetry that exists in the interrelation of flatMap / foldMap / traverse and flatten / fold / sequence.
Armed with an understanding of foldM, we then look at how such a function can be used to implement an iterative algorithm for the N-Queens puzzle.
The talk ends by pointing out that the iterative algorithm is smarter than the recursive one, because it ‘remembers’ where it has already placed previous queens.
download for better quality - Learn about the sequence and traverse functions
through the work of Runar Bjarnason and Paul Chiusano, authors of Functional Programming in Scala https://www.manning.com/books/functional-programming-in-scala
The Functional Programming Triad of Map, Filter and FoldPhilip Schwarz
This slide deck is my homage to SICP, the book which first introduced me to the Functional Programming triad of map, filter and fold.
It was during my Computer Science degree that a fellow student gave me a copy of the first edition, not long after the book came out.
I have not yet come across a better introduction to these three functions.
The upcoming slides are closely based on the second edition of the book, a free online copy of which can be found here:
https://mitpress.mit.edu/sites/default/files/sicp/full-text/book/book.html.
Download for original image quality.
Errata:
slide 20: the Clojure map function is in fact the Scheme one repeated - see code below for correction.
Scheme code: https://github.com/philipschwarz/the-fp-triad-of-map-filter-and-fold-scheme
Clojure code: https://github.com/philipschwarz/the-fp-triad-of-map-filter-and-fold-clojure
The document discusses object-oriented programming (OOP) and functional programming (FP). It argues that OOP and FP are not opposites and can be effectively combined. It addresses common myths about FP, such as that it is new, hard, or only suitable for mathematical problems. The document also compares how OOP and FP approach concepts like decomposition, composition, error handling, and mutability/referential transparency. While both approaches have merits, the document concludes there is no single best approach and the choice depends on the problem and programmer preferences.
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part ...Philip Schwarz
(download for best quality slides) Gain a deeper understanding of why right folds over very large and infinite lists are sometimes possible in Haskell.
See how lazy evaluation and function strictness affect left and right folds in Haskell.
Learn when an ordinary left fold results in a space leak and how to avoid it using a strict left fold.
This version eliminates some minor imperfections and corrects the following two errors:
slide 15: "as sharing is required" should be "as sharing is not required"
slide 43: 푠푓표푙푑푙 (⊕) 푎 should be 푠푓표푙푑푙 (⊕) 푒
The document describes several algorithms related to graph searching and optimization problems:
1) Binary search and depth-first search algorithms for searching arrays and graphs.
2) Breadth-first search and shortest path algorithms using BFS for graphs.
3) Topological sort and n-queens algorithms using backtracking to solve optimization problems on graphs and boards.
4) Hamiltonian cycle algorithm applying backtracking to find cycles in graphs.
The algorithms are represented using pseudocode with common structures like adjacency lists, matrices, queues, and recursion to traverse and search data structures efficiently.
The document describes several algorithms related to graph searching and optimization problems:
1) Binary search and depth-first search algorithms for searching arrays and graphs.
2) Breadth-first search for graphs and finding shortest paths.
3) Topological sorting of directed acyclic graphs.
4) Backtracking algorithms for solving the n-queens problem and searching for Hamiltonian cycles in graphs.
Algorithm Performance For Chessboard Separation ProblemsTina Gabel
The document discusses algorithms for solving variations of chessboard placement problems, specifically the N + k Queens Problem. It presents results comparing the performance of sequential and parallel programs that use backtracking and dancing links algorithms to count solutions. Dancing links was found to outperform backtracking for larger problem sizes. The parallel dancing links implementation distributed work by assigning each processor a unique starting position for the first pawn.
The document discusses backtracking methodology for solving problems. It involves representing solutions as n-tuples and searching the solution space tree using depth-first search. Nodes are marked as live, dead, or the current node being expanded (E-node). Bounding functions help prune portions of the tree and avoid searching invalid or non-optimal subtrees. The 4-Queens problem is used as an example to illustrate backtracking.
This document discusses backtracking as an algorithm design technique. It provides examples of problems that can be solved using backtracking, including the 8 queens problem, sum of subsets, graph coloring, Hamiltonian cycles, and the knapsack problem. It also provides pseudocode for general backtracking algorithms and algorithms for specific problems solved through backtracking.
The document discusses various algorithms that can be solved using backtracking. It begins by defining backtracking as a general algorithm design technique for problems that involve searching for solutions satisfying constraints. It then provides examples of problems that can be solved using backtracking, including the 8 queens problem, sum of subsets, graph coloring, and finding Hamiltonian cycles in a graph. For each problem, it outlines the key steps and provides pseudocode for the backtracking algorithm.
Analysis & Design of Algorithms
Backtracking
N-Queens Problem
Hamiltonian circuit
Graph coloring
A presentation on unit Backtracking from the ADA subject of Engineering.
The document discusses backtracking as a general method for solving problems that involve systematically trying possibilities and abandoning partial solutions when they cannot possibly lead to a complete solution. It provides examples of applications of backtracking including the n-queens problem, sum of subsets problem, graph coloring, and finding Hamiltonian cycles in graphs. The general backtracking algorithm and terminology used are described. Specific algorithms for solving the n-queens problem and sum of subsets problem using backtracking are also presented.
Backtracking is an algorithmic technique for solving problems by incrementally building candidates to the solutions, and abandoning each partial candidate ("backtracking") as soon as it is determined that the candidate cannot possibly be completed to a valid solution. The document provides examples of problems that can be solved using backtracking, including the traveling salesperson problem and the n-queens problem. It also describes how backtracking works by traversing a tree of possible candidates in a depth-first manner.
This document presents an overview of the N-Queens problem and the backtracking algorithm used to solve it. The N-Queens problem aims to place N queens on an N×N chessboard so that no two queens attack each other. The document outlines the constraints of the problem, explores the solution space using a state space tree representation, provides pseudocode for the backtracking algorithm, and analyzes the time complexity which is O(N!). Examples are given for solving the 4-Queens problem using backtracking.
The document provides five rules for presenting code in slides: 1) Use a monospaced font for readability, 2) Use large fonts that are visible from the back of the room, 3) Only highlight syntax where needed to avoid walls of text, 4) Use ellipses (...) to remove unnecessary code, and 5) Add annotations to draw attention to specific parts of the code. It then demonstrates these rules by presenting an example of using promises in JavaScript to avoid nested callbacks.
N Queen Problem using Branch And Bound - GeeksforGeeks.pdfakashreddy966699
The document discusses the N queens puzzle and its solution using the branch and bound algorithm. The N queens puzzle aims to place N chess queens on an N×N chessboard so that no two queens threaten each other. The branch and bound solution avoids exploring paths that cannot lead to a valid solution. Pseudocode and implementations in C++ and Java are provided to demonstrate solving the N queens puzzle using branch and bound.
The document introduces the concept of a vector space, which is a set along with two operations - addition and scalar multiplication - that satisfy certain properties. Examples of vector spaces include Rn (the set of n-tuples of real numbers) with the usual vector addition and scalar multiplication. A plane through the origin in R3 is also a vector space by inheriting the vector space structure of R3. The set of polynomials of degree three or less with coefficients in R is another example of a vector space.
I am Nigel J. I am a Computer Network Assignment Expert at computernetworkassignmenthelp.com. I hold a Master's in Computer Science from, the University of Glasgow, UK. I have been helping students with their assignments for the past 15 years. I solve assignments related to Computer Networks.
Visit computernetworkassignmenthelp.com or email support@computernetworkassignmenthelp.com.
You can also call on +1 678 648 4277 for any assistance with Computer Network Assignment.
Backtracking is an algorithm that systematically searches for solutions to a problem by exploring all potential candidates. It works by assuming solutions can be represented as vectors, and traversing the domain of these vectors in a depth-first manner until it finds solutions. When a partial vector is found not to represent a partial solution, it backtracks by removing the last value added and trying alternative values. Examples where backtracking can be applied include the traveling salesperson problem and the n queens problem.
The document defines equivalence relation and provides two examples. It then proves some properties about equivalence relations on real numbers. It proves mathematical induction for a formula relating sums and cubes. It proves properties about spanning trees and connectivity in graphs. It also proves that congruence modulo m is an equivalence relation by showing it satisfies the properties of reflexivity, symmetry, and transitivity. Finally, it explains the concepts of transition graphs and transition tables for representing finite state automata.
The document discusses recursive definitions of sequences, functions, sets, and strings. It provides examples of recursively defining the Fibonacci sequence, factorial function, set of prices using quarters and dimes, and set of binary numbers. It also discusses recursively defining the length, empty string, concatenation, and reversal of strings.
The document summarizes the disjoint-set data structure and algorithms for implementing union-find operations on disjoint sets. Key points:
- Disjoint sets allow representing partitions of elements into disjoint groups and supporting operations to merge groups and find the group a element belongs to.
- Several implementations are described, including linked lists and rooted trees (forests).
- The weighted-union heuristic improves the naive linked list implementation from O(n^2) to O(m log n) time by merging shorter lists into longer ones.
- In forests, union-by-rank and path compression heuristics combine sets in nearly linear time by balancing tree heights and flattening paths during finds.
This document summarizes a lecture on satisfiability and NP-completeness. It introduces the satisfiability problem and shows that 3-SAT, the problem of determining if a Boolean formula consisting of clauses with 3 literals can be satisfied, is NP-complete by reducing SAT to it. It then shows other problems like vertex cover and maximum clique are NP-complete by reducing 3-SAT to them. Reductions preserve the computational difficulty of problems.
The document discusses various backtracking techniques including bounding functions, promising functions, and pruning to avoid exploring unnecessary paths. It provides examples of problems that can be solved using backtracking including n-queens, graph coloring, Hamiltonian circuits, sum-of-subsets, 0-1 knapsack. Search techniques for backtracking problems include depth-first search (DFS), breadth-first search (BFS), and best-first search combined with branch-and-bound pruning.
Similar to N-Queens Combinatorial Problem - Polyglot FP for Fun and Profit – Haskell and Scala - Part 1 (20)
Hand Rolled Applicative User ValidationCode KataPhilip Schwarz
Could you use a simple piece of Scala validation code (granted, a very simplistic one too!) that you can rewrite, now and again, to refresh your basic understanding of Applicative operators <*>, <*, *>?
The goal is not to write perfect code showcasing validation, but rather, to provide a small, rough-and ready exercise to reinforce your muscle-memory.
Despite its grandiose-sounding title, this deck consists of just three slides showing the Scala 3 code to be rewritten whenever the details of the operators begin to fade away.
The code is my rough and ready translation of a Haskell user-validation program found in a book called Finding Success (and Failure) in Haskell - Fall in love with applicative functors.
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidPhilip Schwarz
The subject of this deck is the small Print[A] program in the following blog post by Noel Welsh: https://www.inner-product.com/posts/direct-style-effects/.
Keywords: "direct-style", "context function", "context functions", "algebraic effect", "algebraic effects", "scala", "effect system", "effect systems", "effect", "side effect", "composition", "fp", "functional programming"
Folding Cheat Sheet #4 - fourth in a seriesPhilip Schwarz
For functions that can be defined both as an instance of a right fold and as an instance of a left fold, one may be more efficient than the other.
Let's look at the example of a function 'decimal' that converts a list of digits into the corresponding decimal number.
Erratum: it has been pointed out that it is possible to define the zip function using a right fold (see slide 5).
Folding Cheat Sheet #3 - third in a seriesPhilip Schwarz
This document summarizes the universal property of fold, which states that for finite lists the fold function is the unique function that satisfies its defining recursive equations. It provides examples of how common list functions like sum, product, length, concatenation (⧺) can be defined in terms of fold. It also notes that the universal property can be generalized to handle partial and infinite lists. Finally, it states that map, filter and fold form the "triad" or basic building blocks of functional programming.
Folding Cheat Sheet #2 - second in a seriesPhilip Schwarz
This document provides definitions and examples of foldr and foldl functions in functional programming. Foldr recursively applies a function from right to left, associating at each step. Foldl recursively applies a function from left to right, associating at each step. Examples are given applying foldr and foldl to a list with elements a0 through a3, using a function f and initial value b. Programmatic and mathematical definitions of foldr and foldl are also presented.
Folding Cheat Sheet #1 - first in a seriesPhilip Schwarz
This document provides examples of using fold functions to define recursive functions over natural numbers (Nat) and lists. It shows common patterns for defining recursive functions over Nat using foldn and over lists using foldr. Three examples are given of functions defined over Nat using foldn: addition, multiplication, and exponentiation. Three examples are also given of functions defined over lists using foldr: sum, length, and append.
Tagless Final Encoding - Algebras and Interpreters and also ProgramsPhilip Schwarz
Tagless Final Encoding - Algebras and Interpreters and also Programs - An introduction, through the work of Gabriel Volpe.
Slide deck home: http://fpilluminated.com/assets/tagless-final-encoding-algebras-interpreters-and-programs.html
A sighting of traverseFilter and foldMap in Practical FP in ScalaPhilip Schwarz
Slide deck home: http://fpilluminated.com/assets/sighting-of-scala-cats-traverseFilter-and-foldMap-in-practical-fp-in-scala.html.
Download PDF for perfect image quality.
A sighting of sequence function in Practical FP in ScalaPhilip Schwarz
Slide deck home: http://fpilluminated.com/assets/sighting-of-scala-cats-sequence-function-in-practical-fp-in-scala.html.
Download PDF for perfect image quality.
Kleisli composition, flatMap, join, map, unit - implementation and interrelat...Philip Schwarz
Kleisli composition, flatMap, join, map, unit. A study/memory aid, to help learn/recall their implementation/interrelation.
Version 2, updated for Scala 3
Nat, List and Option Monoids -from scratch -Combining and Folding -an examplePhilip Schwarz
Nat, List and Option Monoids, from scratch. Combining and Folding: an example.
This is a new version of the original which has some cosmetic changes and a new 7th slide which only differs from slide 6 in that it defines the fold function in terms of the foldRight function.
Code: https://github.com/philipschwarz/nat-list-and-option-monoids-from-scratch-combining-and-folding-an-example
The Sieve of Eratosthenes - Part II - Genuine versus Unfaithful Sieve - Haske...Philip Schwarz
When I posted the deck for Part 1 to the Scala users forum, Odd Möller linked to a paper titled "The Genuine Sieve of Eratosthenes", which speaks of the Unfaithful Sieve.
Part 2 is based on that paper and on Richard Bird's faithful Haskell implementation of the Sieve, which we translate into Scala.
Scala code for Richard Bird's infinite primes Haskell program: https://github.com/philipschwarz/sieve-of-eratosthenes-part-2-scala
Jordan Peterson - The pursuit of meaning and related ethical axiomsPhilip Schwarz
I have only recently become aware of the work of Jordan Peterson. Because I am finding it so interesting, I hope that the following small collection of excerpts from some of his writings and speeches might entice any fellow latecomers to find out more about his work. See below for my own summary of some of the subjects touched upon in these slides.
Download for best results.
Defining filter using (a) recursion (b) folding (c) folding with S, B and I c...Philip Schwarz
Defining filter using
(a) recursion
(b) folding
(c) folding with S, B and I combinators
(d) folding with applicative functor and identity function.pdf
This second version adds a simpler folding definition, which I had left out in the first version.
The Sieve of Eratosthenes - Part 1 - with minor correctionsPhilip Schwarz
In this slide deck we are going to see some examples of how the effort required to read an understand the Sieve of Eratosthenes varies greatly depending on the programming paradigm used to implement the algorithm.
We'll see code in Java, Scheme, Haskell and Scala.
This version of the deck contains some minor corrections (see errata section in first version for details)
Do you want Software for your Business? Visit Deuglo
Deuglo has top Software Developers in India. They are experts in software development and help design and create custom Software solutions.
Deuglo follows seven steps methods for delivering their services to their customers. They called it the Software development life cycle process (SDLC).
Requirement — Collecting the Requirements is the first Phase in the SSLC process.
Feasibility Study — after completing the requirement process they move to the design phase.
Design — in this phase, they start designing the software.
Coding — when designing is completed, the developers start coding for the software.
Testing — in this phase when the coding of the software is done the testing team will start testing.
Installation — after completion of testing, the application opens to the live server and launches!
Maintenance — after completing the software development, customers start using the software.
AI Pilot Review: The World’s First Virtual Assistant Marketing SuiteGoogle
AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
👉👉 Click Here To Get More Info 👇👇
https://sumonreview.com/ai-pilot-review/
AI Pilot Review: Key Features
✅Deploy AI expert bots in Any Niche With Just A Click
✅With one keyword, generate complete funnels, websites, landing pages, and more.
✅More than 85 AI features are included in the AI pilot.
✅No setup or configuration; use your voice (like Siri) to do whatever you want.
✅You Can Use AI Pilot To Create your version of AI Pilot And Charge People For It…
✅ZERO Manual Work With AI Pilot. Never write, Design, Or Code Again.
✅ZERO Limits On Features Or Usages
✅Use Our AI-powered Traffic To Get Hundreds Of Customers
✅No Complicated Setup: Get Up And Running In 2 Minutes
✅99.99% Up-Time Guaranteed
✅30 Days Money-Back Guarantee
✅ZERO Upfront Cost
See My Other Reviews Article:
(1) TubeTrivia AI Review: https://sumonreview.com/tubetrivia-ai-review
(2) SocioWave Review: https://sumonreview.com/sociowave-review
(3) AI Partner & Profit Review: https://sumonreview.com/ai-partner-profit-review
(4) AI Ebook Suite Review: https://sumonreview.com/ai-ebook-suite-review
DDS Security Version 1.2 was adopted in 2024. This revision strengthens support for long runnings systems adding new cryptographic algorithms, certificate revocation, and hardness against DoS attacks.
Launch Your Streaming Platforms in MinutesRoshan Dwivedi
The claim of launching a streaming platform in minutes might be a bit of an exaggeration, but there are services that can significantly streamline the process. Here's a breakdown:
Pros of Speedy Streaming Platform Launch Services:
No coding required: These services often use drag-and-drop interfaces or pre-built templates, eliminating the need for programming knowledge.
Faster setup: Compared to building from scratch, these platforms can get you up and running much quicker.
All-in-one solutions: Many services offer features like content management systems (CMS), video players, and monetization tools, reducing the need for multiple integrations.
Things to Consider:
Limited customization: These platforms may offer less flexibility in design and functionality compared to custom-built solutions.
Scalability: As your audience grows, you might need to upgrade to a more robust platform or encounter limitations with the "quick launch" option.
Features: Carefully evaluate which features are included and if they meet your specific needs (e.g., live streaming, subscription options).
Examples of Services for Launching Streaming Platforms:
Muvi [muvi com]
Uscreen [usencreen tv]
Alternatives to Consider:
Existing Streaming platforms: Platforms like YouTube or Twitch might be suitable for basic streaming needs, though monetization options might be limited.
Custom Development: While more time-consuming, custom development offers the most control and flexibility for your platform.
Overall, launching a streaming platform in minutes might not be entirely realistic, but these services can significantly speed up the process compared to building from scratch. Carefully consider your needs and budget when choosing the best option for you.
May Marketo Masterclass, London MUG May 22 2024.pdfAdele Miller
Can't make Adobe Summit in Vegas? No sweat because the EMEA Marketo Engage Champions are coming to London to share their Summit sessions, insights and more!
This is a MUG with a twist you don't want to miss.
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptxrickgrimesss22
Discover the essential features to incorporate in your Winzo clone app to boost business growth, enhance user engagement, and drive revenue. Learn how to create a compelling gaming experience that stands out in the competitive market.
Atelier - Innover avec l’IA Générative et les graphes de connaissancesNeo4j
Atelier - Innover avec l’IA Générative et les graphes de connaissances
Allez au-delà du battage médiatique autour de l’IA et découvrez des techniques pratiques pour utiliser l’IA de manière responsable à travers les données de votre organisation. Explorez comment utiliser les graphes de connaissances pour augmenter la précision, la transparence et la capacité d’explication dans les systèmes d’IA générative. Vous partirez avec une expérience pratique combinant les relations entre les données et les LLM pour apporter du contexte spécifique à votre domaine et améliorer votre raisonnement.
Amenez votre ordinateur portable et nous vous guiderons sur la mise en place de votre propre pile d’IA générative, en vous fournissant des exemples pratiques et codés pour démarrer en quelques minutes.
Neo4j - Product Vision and Knowledge Graphs - GraphSummit ParisNeo4j
Dr. Jesús Barrasa, Head of Solutions Architecture for EMEA, Neo4j
Découvrez les dernières innovations de Neo4j, et notamment les dernières intégrations cloud et les améliorations produits qui font de Neo4j un choix essentiel pour les développeurs qui créent des applications avec des données interconnectées et de l’IA générative.
Enterprise Resource Planning System includes various modules that reduce any business's workload. Additionally, it organizes the workflows, which drives towards enhancing productivity. Here are a detailed explanation of the ERP modules. Going through the points will help you understand how the software is changing the work dynamics.
To know more details here: https://blogs.nyggs.com/nyggs/enterprise-resource-planning-erp-system-modules/
Essentials of Automations: The Art of Triggers and Actions in FMESafe Software
In this second installment of our Essentials of Automations webinar series, we’ll explore the landscape of triggers and actions, guiding you through the nuances of authoring and adapting workspaces for seamless automations. Gain an understanding of the full spectrum of triggers and actions available in FME, empowering you to enhance your workspaces for efficient automation.
We’ll kick things off by showcasing the most commonly used event-based triggers, introducing you to various automation workflows like manual triggers, schedules, directory watchers, and more. Plus, see how these elements play out in real scenarios.
Whether you’re tweaking your current setup or building from the ground up, this session will arm you with the tools and insights needed to transform your FME usage into a powerhouse of productivity. Join us to discover effective strategies that simplify complex processes, enhancing your productivity and transforming your data management practices with FME. Let’s turn complexity into clarity and make your workspaces work wonders!
Code reviews are vital for ensuring good code quality. They serve as one of our last lines of defense against bugs and subpar code reaching production.
Yet, they often turn into annoying tasks riddled with frustration, hostility, unclear feedback and lack of standards. How can we improve this crucial process?
In this session we will cover:
- The Art of Effective Code Reviews
- Streamlining the Review Process
- Elevating Reviews with Automated Tools
By the end of this presentation, you'll have the knowledge on how to organize and improve your code review proces
E-commerce Application Development Company.pdfHornet Dynamics
Your business can reach new heights with our assistance as we design solutions that are specifically appropriate for your goals and vision. Our eCommerce application solutions can digitally coordinate all retail operations processes to meet the demands of the marketplace while maintaining business continuity.
Zoom is a comprehensive platform designed to connect individuals and teams efficiently. With its user-friendly interface and powerful features, Zoom has become a go-to solution for virtual communication and collaboration. It offers a range of tools, including virtual meetings, team chat, VoIP phone systems, online whiteboards, and AI companions, to streamline workflows and enhance productivity.
Transform Your Communication with Cloud-Based IVR SolutionsTheSMSPoint
Discover the power of Cloud-Based IVR Solutions to streamline communication processes. Embrace scalability and cost-efficiency while enhancing customer experiences with features like automated call routing and voice recognition. Accessible from anywhere, these solutions integrate seamlessly with existing systems, providing real-time analytics for continuous improvement. Revolutionize your communication strategy today with Cloud-Based IVR Solutions. Learn more at: https://thesmspoint.com/channel/cloud-telephony
Transform Your Communication with Cloud-Based IVR Solutions
N-Queens Combinatorial Problem - Polyglot FP for Fun and Profit – Haskell and Scala - Part 1
1. N-Queens Combinatorial Problem
first see the problem solved using the List monad and a Scala for comprehension
then see the Scala program translated into Haskell, both using a do expressions and using a List comprehension
understand how the Scala for comprehension is desugared, and what role the withFilter function plays
also understand how the Haskell do expressions and List comprehension are desugared, and what role the guard function plays
Miran Lipovača
Polyglot FP for Fun and Profit – Haskell and Scala
@philip_schwarz
slides by https://www.slideshare.net/pjschwarz
Bill Venners
Martin Odersky
Part 1
based on, and inspired by, the work of
Lex Spoon
2. Yes, I know, Lex Spoon looks a bit too young in that photo, and Bill Venner’s hair doesn’t look realistic in that drawing. Martin
Odersky’s drawing is not bad at all.
By the way, don’t be put off by the fact that the book image below is of the fourth edition. Excerpts from the N-queens section of
that edition are great, and by the way, in the fifth edition (new for Scala 3) I don’t see that section (it may have moved to upcoming
book Advanced Programming in Scala). Also, I do use Scala 3 in this slide deck.
Bill Venners
Martin Odersky
Lex Spoon
@philip_schwarz
3. A particularly suitable application area of for expressions are
combinatorial puzzles.
An example of such a puzzle is the 8-queens problem: Given a
standard chess-board, place eight queens such that no queen is
in check from any other (a queen can check another piece if they
are on the same column, row, or diagonal).
To find a solution to this problem, it’s actually simpler to generalize it to chess-
boards of arbitrary size.
Hence the problem is to place N queens on a chess-board of N x N squares, where
the size N is arbitrary.
We’ll start numbering cells at one, so the upper-left cell of an N x N board has
coordinate (1,1) and the lower-right cell has coordinate (N,N).
To solve the N-queens problem, note that you need to place a queen in each row.
So you could place queens in successive rows, each time checking that a newly
placed queen is not in check from any other queens that have already been placed.
In the course of this search, it might happen that a queen that needs to be placed in
row k would be in check in all fields of that row from queens in row 1 to k - 1. In
that case, you need to abort that part of the search in order to continue with a
different configuration of queens in columns 1 to k - 1.
Here on the right is a sample
solution to the puzzle.
And below is an example in which there is
nowhere to place queen number 6
because every other cell on the board is in
check from queens 1 to 5.
4. An imperative solution to this problem would place queens one by one, moving
them around on the board.
But it looks difficult to come up with a scheme that really tries all possibilities.
A more functional approach represents a solution directly, as a value. A solution
consists of a list of coordinates, one for each queen placed on the board.
Note, however, that a full solution can not be found in a single step. It needs to be
built up gradually, by occupying successive rows with queens.
This suggests a recursive algorithm.
Assume you have already generated all solutions of placing k queens on a board
of size N x N, where k is less than N.
Each solution can be represented by a list of length k of coordinates (row,
column), where both row and column numbers range from 1 to N.
It’s convenient to treat these partial solution lists as stacks, where the
coordinates of the queen in row k come first in the list, followed by the
coordinates of the queen in row k - 1, and so on.
The bottom of the stack is the coordinate of the queen placed in the first row of
the board.
All solutions together are represented as a list of lists, with one element for each
solution.
List((8, 6), (7, 3),
(6, 7), (5, 2),
(4, 8), (3, 5),
(2, 1), (1, 4))
See below for the list representing the
above solution to the 8-queens puzzle.
(7, 3)
(8, 6)
(6, 7)
(5, 2)
(4, 8)
(3, 5)
(2, 1)
(1, 4)
R C
O O
W L
5. Now, to place the next queen in row k + 1, generate all possible extensions of each previous solution
by one more queen.
This yields another list of solutions lists, this time of length k + 1.
Continue the process until you have obtained all solutions of the size of the chess-board N.
This algorithmic idea is embodied in function placeQueens below:
The outer function queens in the program above simply calls placeQueens with the size of the board n
as its argument.
The task of the function application placeQueens(k) is to generate all partial solutions of length k in a
list.
Every element of the list is one solution, represented by a list of length k. So placeQueens returns a list
of lists.
def queens(n: Int): List[List[(Int,Int)]] = {
def placeQueens(k: Int): List[List[(Int,Int)]] =
if (k == 0)
List(List())
else
for {
queens <- placeQueens(k - 1)
column <- 1 to n
queen = (k, column)
if isSafe(queen, queens)
} yield queen :: queens
placeQueens(n)
}
List((8, 6), (7, 3),
(6, 7), (5, 2),
(4, 8), (3, 5),
(2, 1), (1, 4))
6. If the parameter k to placeQueens is 0, this means that it needs to generate all solutions of
placing zero queens on zero rows. There is only one solution: place no queen at all. This
solution is represented by the empty list. So if k is zero, placeQueens returns List(List()), a
list consisting of a single element that is the empty list.
Note that this is quite different from the empty list List(). If placeQueens returns List(), this
means no solutions, instead of a single solution consisting of no placed queens.
In the other case, where k is not zero, all the work of placeQueens is done in the for
expression.
The first generator of that for expression iterates through all solutions of placing k - 1 queens on
the board.
The second generator iterates through all possible columns on which the kth queen might be
placed.
The third part of the for expression defines the newly considered queen position to be the pair
consisting of row k and each produced column.
The fourth part of the for expression is a filter which checks with isSafe whether the new
queen is safe from check by all previous queens (the definition of isSafe will be discussed a bit
later.)
If the new queen is not in check from any other queens, it can form part of a partial solution, so
placeQueens generates with queen::queens a new solution.
If the new queen is not safe from check, the filter returns false, so no solution is generated.
for {
queens <- placeQueens(k - 1)
column <- 1 to n
queen = (k, column)
if isSafe(queen, queens)
} yield queen :: queens
Here is the for expression
again, for reference.
7. The only remaining bit is the isSafe method, which is used to check whether a given queen is in check from any other element
in a list of queens.
Here is the definition:
The isSafe method expresses that a queen is safe with respect to some other queens if it is not in check from any other queen.
The inCheck method expresses that queens q1 and q2 are mutually in check.
It returns true in one of three cases:
1. If the two queens have the same row coordinate.
2. If the two queens have the same column coordinate.
3. If the two queens are on the same diagonal (i.e., the difference between their rows and the difference between their
columns are the same).
The first case – that the two queens have the same row coordinate – cannot happen in the application because placeQueens
already takes care to place each queen in a different row. So you could remove the test without changing the functionality of the
program.
def isSafe(queen: (Int, Int), queens: List[(Int, Int)]) =
queens forall (q => !inCheck(queen, q))
def inCheck(q1: (Int, Int), q2: (Int, Int)) =
q1._1 == q2._1 || // same row
q1._2 == q2._2 || // same column
(q1._1 - q2._1).abs == (q1._2 - q2._2).abs // on diagonal
8. (6, 2)
(7, 5)
(5, 6)
(4, 1)
(3, 7)
(2, 4)
(1, 0)
(0, 3) In online course FP in Scala, the board
coordinates are zero-based, and since
it is obvious that the nth queen is in row
n, a solution is a list of column indices
rather than a list of coordinate pairs.
List(5, 2, 6, 1, 7, 4, 0, 3) @philip_schwarz
9. Because a column index is sufficient to indicate the coordinates of the nth queen, we can see that the type of isSafe’s first parameter is now Int, i.e. a
column index, rather than (Int, Int) i.e. a coordinate pair.
Also, the type of a solution is List[Int] rather than List[(Int, Int)], and solutions are returned in a Set, rather than a List, to distinguish between a
single solution, which is an ordered list, and the collection of all solutions, which is not ordered (though it could be, if we so wanted).
10. def queens(n: Int): List[List[(Int,Int)]] = {
def placeQueens(k: Int): List[List[(Int,Int)]] =
if (k == 0)
List(List())
else
for {
queens <- placeQueens(k - 1)
column <- 1 to n
queen = (k, column)
if isSafe(queen, queens)
} yield queen :: queens
placeQueens(n)
}
def queens(n: Int): Set[List[Int]] = {
def placeQueens(k: Int): Set[List[Int]] =
if (k == 0)
Set(List())
else
for {
queens <- placeQueens(k - 1)
col <- 0 until n
if isSafe(col, queens)
} yield col :: queens
placeQueens(n)
}
def isSafe(queen: (Int, Int), queens: List[(Int, Int)]) =
queens forall (q => !inCheck(queen, q))
def inCheck(q1: (Int, Int), q2: (Int, Int)) =
q1._1 == q2._1 || // same row
q1._2 == q2._2 || // same column
(q1._1 - q2._1).abs == (q1._2 - q2._2).abs // on diagonal
def isSafe(col: Int, queens: List[Int]): Boolean = {
val row = queens.length
val queensWithRow = (row - 1 to 0 by -1) zip queens
queensWithRow forall
{ case (r, c) => col != c && math.abs(col - c) != row - r }
}
Here are the two versions of
the program side by side.
11. def queens(n: Int): List[List[(Int,Int)]] =
def placeQueens(k: Int): List[List[(Int,Int)]] =
if k == 0
then List(List())
else
for
queens <- placeQueens(k - 1)
column <- 1 to n
queen = (k, column)
if isSafe(queen, queens)
yield queen :: queens
placeQueens(n)
def isSafe(queen: (Int, Int), queens: List[(Int, Int)]) =
queens forall (q => !inCheck(queen, q))
def inCheck(queen1: (Int, Int), queen2: (Int, Int)) =
queen1(0) == queen2(0) || // same row
queen1(1) == queen2(1) || // same column
(queen1(0) - queen2(0)).abs == (queen1(1) - queen2(1)).abs // on diagonal
def queens(n: Int): Set[List[Int]] =
def placeQueens(k: Int): Set[List[Int]] =
if k == 0
then Set(List())
else
for
queens <- placeQueens(k - 1)
col <- 0 until n
if isSafe(col, queens)
yield col :: queens
placeQueens(n)
def isSafe(col: Int, queens: List[Int]): Boolean =
val row = queens.length
val queensWithRow = (row - 1 to 0 by -1) zip queens
queensWithRow forall
{ case (r, c) => col != c && math.abs(col - c) != row - r }
Same as on the previous slide, but with
really minor tweaks thanks to Scala 3
12. def queens(n: Int): List[List[Int]] =
def placeQueens(k: Int): List[List[Int]] =
if k == 0
then List(List())
else
for
queens <- placeQueens(k - 1)
queen <- 1 to n
if safe(queen, queens)
yield queen :: queens
placeQueens(n)
def onDiagonal(row: Int, column: Int, otherRow: Int, otherColumn: Int) =
math.abs(row - otherRow) == math.abs(column - otherColumn)
def zipWithRows(queens: List[Int]): Iterable[(Int,Int)] =
val rowCount = queens.length
val rowNumbers = rowCount - 1 to 0 by -1
rowNumbers zip queens
def safe(queen: Int, queens: List[Int]): Boolean =
val (row, column) = (queens.length, queen)
val safe: ((Int,Int)) => Boolean = (nextRow, nextColumn) =>
column != nextColumn && !onDiagonal(column, row, nextColumn, nextRow)
zipWithRows(queens) forall safe
In the next part of this slide deck, we are going to
be using the program on the right.
The queens and placeQueens functions are pretty
much the same as in the second version on the
previous slide, but board coordinates are one-
based, and the two functions return a List rather
than a Set.
The logic for determining if a queen is safe from
previously placed queens, is organised in a way that
is in part a hybrid between the two programs on
the previous slide.
(7, 3)
(8, 6)
(6, 7)
(5, 2)
(4, 8)
(3, 5)
(2, 1)
(1, 4)
List(6, 3, 7, 2, 8, 5, 1, 4)
assert(queens(4) == List(List(3, 1, 4, 2), List(2, 4, 1, 3)))
assert(queens(6) == List(List(3, 6, 2, 5, 1, 4),
List(4, 1, 5, 2, 6, 3),
List(5, 3, 1, 6, 4, 2),
List(2, 4, 6, 1, 3, 5)))
@philip_schwarz
13. The first thing we are going to do, is translate our N-queens
program from Scala into Haskell.
Let’s start with the queens and placeQueens functions.
queens n = placeQueens n
where
placeQueens 0 = [[]]
placeQueens k =
do
queens <- placeQueens(k-1)
queen <- [1..n]
guard (safe queen queens)
return (queen:queens)
def queens(n: Int): List[List[Int]] =
def placeQueens(k: Int): List[List[Int]] =
if k == 0
then List(List())
else
for
queens <- placeQueens(k - 1)
queen <- 1 to n
if safe(queen, queens)
yield queen :: queens
placeQueens(n)
In Scala we use a for comprehension,
whereas in Haskell we use a do expression.
In Scala, the filtering is done by
if safe(queen, queens)
whereas in Haskell it is done by
guard (safe queen queens)
If you are asking yourself what the guard function
is, don’t worry: we’ll be looking at it soon.
14. queens n = placeQueens n
where
placeQueens 0 = [[]]
placeQueens k = do
queens <- placeQueens(k-1)
queen <- [1..n]
guard (safe queen queens)
return (queen:queens)
queens n = placeQueens n
where
placeQueens 0 = [[]]
placeQueens k =
[queen:queens |
queens <- placeQueens(k-1),
queen <- [1..n],
safe queen queens]
We can simplify the Haskell version a little bit by eliminating
the calls to guard and return, which can be achieved by
switching from a do expression to a list comprehension.
If you are asking yourself how the list
comprehension eliminates the need for guard and
return, don’t worry: we’ll be looking at that soon.
15. queens n = placeQueens n
where
placeQueens 0 = [[]]
placeQueens k = [queen:queens |
queens <- placeQueens(k-1),
queen <- [1..n],
safe queen queens]
safe queen queens = all safe (zipWithRows queens)
where
safe (r,c) = c /= col && not (onDiagonal col row c r)
row = length queens
col = queen
onDiagonal row column otherRow otherColumn =
abs (row - otherRow) == abs (column - otherColumn)
zipWithRows queens = zip rowNumbers queens
where
rowCount = length queens
rowNumbers = [rowCount-1,rowCount-2..0]
def queens(n: Int): List[List[Int]] =
def placeQueens(k: Int): List[List[Int]] =
if k == 0
then List(List())
else
for
queens <- placeQueens(k - 1)
queen <- 1 to n
if safe(queen, queens)
yield queen :: queens
placeQueens(n)
def onDiagonal(row: Int, column: Int, otherRow: Int, otherColumn: Int) =
math.abs(row - otherRow) == math.abs(column - otherColumn)
def safe(queen: Int, queens: List[Int]): Boolean =
val (row, column) = (queens.length, queen)
val safe: ((Int,Int)) => Boolean = (nextRow, nextColumn) =>
column != nextColumn && !onDiagonal(column, row, nextColumn, nextRow)
zipWithRows(queens) forall safe
def zipWithRows(queens: List[Int]): Iterable[(Int,Int)] =
val rowCount = queens.length
val rowNumbers = rowCount - 1 to 0 by -1
rowNumbers zip queens
And here is the translation
of the whole program
17. N N-queens solution count
1 1
2 0
3 0
4 2
5 10
6 4
7 40
8 92
9 352
10 724
11 2,680
12 14,200
13 73,712
14 365,596
15 2,279,184
16 14,772,512
17 95,815,104
18 666,090,624
19 4,968,057,848
20 39,029,188,884
21 314,666,222,712
22 2,691,008,701,644
23 24,233,937,684,440
24 227,514,171,973,736
25 2,207,893,435,808,352
26 22,317,699,616,364,044
27 234,907,967,154,122,528
data source: https://en.wikipedia.org/wiki/Eight_queens_puzzle
scala> queens(8).size
val res0: Int = 92
scala> queens(9).size
val res1: Int = 352
scala> queens(10).size
val res2: Int = 724
scala> queens(11).size
val res3: Int = 2680
scala> queens(12).size
val res4: Int = 14200
scala> queens(13).size
val res5: Int = 73712
scala> queens(14).size
val res6: Int = 365596
Haskell> length (queens 8)
92
Haskell> length (queens 9)
352
Haskell> length (queens 10)
724
Haskell> length (queens 11)
2680
Haskell> length (queens 12)
14200
Haskell> length (queens 13)
73712
Haskell> length (queens 14)
365596
For N > 6, the number of solutions is too large for the solutions to
be displayed simply by printing them to the screen.
Let’s at least check that we get the expected number of solutions.
18. In the next five slides, we are going to look at how the Scala
for comprehension is implemented under the hood.
@philip_schwarz
19. for
queens <- placeQueens(k - 1)
queen <- 1 to n
yield queen :: queens
placeQueens(k - 1) flatMap { queens =>
(1 to n) map { queen =>
queen :: queens
}
}
for
nums <- List(List(1,2),List(3,4))
num <- List(10,20)
yield num :: nums
List(List(10, 1, 2), List(20, 1, 2), List(10, 3, 4), List(20, 3, 4))
List(List(1,2),List(3,4)) flatMap { nums =>
List(10,20) map { num =>
num :: nums
}
}
Here is how the N-queens for comprehension, without
the filter, is implemented, i.e. what it looks like when it
is desugared (when its syntactic sugar is removed).
To aid our understanding, here is a similar for
comprehension that is simpler to understand, but can
be run at the REPL, together with its desugared version.
And here is the value produced by both the for
comprehension and its desugared equivalent.
20. for
queens <- placeQueens(k - 1)
queen <- 1 to n
if safe(queen, queens)
yield queen :: queens
placeQueens(k - 1) flatMap { queens =>
(1 to n) withFilter { queen =>
safe(queen, queens)
} map { queen =>
queen :: queens
}
}
Same as on the previous slide, except that now we are adding a filter to the for comprehension.
When the filter is desugared, it results in a call to List’s withFilter function.
for
nums <- List(List(1,2),List(3,4))
num <- List(10,20)
if (num > 15)
yield num :: nums
List(List(1,2),List(3,4)) flatMap { nums =>
List(10,20) withFilter { num =>
num > 15
} map { num =>
num :: nums
}
}
To aid our understanding, here is a similar for
comprehension that is simpler to understand, and that can
be run at the REPL, together with its desugared version.
List(List(20, 1, 2), List(20, 3, 4))
And here is the value produced by both the for comprehension and its desugared equivalent.
21. Let’s see what the withFilter function does:
• it is applied to a monad, in this case a List
• it takes a predicate, i.e. a function that takes a parameter and returns either true or false.
• it applies the predicate to each value yielded by the monad (in this case, each value contained in a List)
• it filters out the values for which the predicate returns false
• It lets through the values for which the predicate returns true
On the next slide, we look at an example of how the behaviour of a for comprehension (or its desugared equivalent) is
affected by the behaviour of the withFilter function.
@philip_schwarz
22. for
nums <- List(List(1,2),List(3,4))
num <- List(10,20)
if (num > 15)
yield num :: nums
List(List(1,2),List(3,4)) flatMap { nums =>
List(10,20) withFilter { num =>
num > 15
} map { num =>
num :: nums
}
}
List(List(20, 1, 2), List(20, 3, 4))
for
nums <- List(List(1,2),List(3,4))
num <- List(10,20)
if (true)
yield num :: nums
List(List(1,2),List(3,4)) flatMap { nums =>
List(10,20) withFilter { num =>
true
} map { num =>
num :: nums
}
}
List(List(10, 1, 2), List(20, 1, 2), List(10, 3, 4), List(20, 3, 4))
for
nums <- List(List(1,2),List(3,4))
num <- List(10,20)
if (false)
yield num :: nums
List(List(1,2),List(3,4)) flatMap { nums =>
List(10,20) withFilter { num =>
false
} map { num =>
num :: nums
}
}
List()
Notice that the predicate function passed to withFilter may or may not
use its parameter. Like the map and flatMap functions, withFilter is
used to bind the value(s) yielded by a monad (if any) to a variable name
which is then available for use in subsequent computations.
withFilter
lets through
some elements
withFilter
lets through
all elements
withFilter
lets through
no elements
The difference is that while the functions passed to map
and flatMap are almost certain to use the variable, in the
case of withFilter, it may choose to influence the
overall computation without actually using the variable.
23. scala> List(1,2,3).withFilter(n => true).map(identity)
val res0: List[Int] = List(1, 2, 3)
scala> List(1,2,3).withFilter(n => n > 1).map(identity)
val res1: List[Int] = List(2, 3)
scala> List(1,2,3).withFilter(n => false).map(identity)
val res2: List[Int] = List()
Before we move on, here is a final, illustration
of what the withFilter function does.
24. Earlier we saw that the do expression that is the Haskell translation of the Scala for
comprehension, involves the use of the guard function.
Also, later we intend to look at how the Haskell do expression is implemented under the hood,
which involves both the guard function and the (>>) function.
So, in the next three slides, we are going to look at how Miran Lipovača explains guard and (>>).
25. Here is the default implementation of the (>>) function:
(>>) :: (Monad m) => ma -> mb -> mb
m >> n = m >>= _ -> n
Normally, passing some value to a function that ignores its parameter and always
returns some predetermined value always results in that predetermined value. With
monads however, their context and meaning must be considered as well.
Here is how >> acts with Maybe:
ghci> Nothing >> Just 3
Nothing
ghci> Just 3 >> Just 4
Just 4
ghci> Just 3 >> Nothing
Nothing
Miran Lipovača
ghci> [] >> [3]
[]
ghci> [3] >> [4]
[4]
ghci> [3] >> []
[]
Here on the
right is how >>
acts with lists.
>>= is Haskell’s equivalent of Scala’s
flatMap and _ -> n is Haskell’s
equivalent of Scala’s anonymous
function _ => n.
scala> List() >> List(3)
val res0: List[Int] = List()
scala> List(3) >> List(4)
val res1: List[Int] = List(4)
scala> List(3) >> List()
val res2: List[Nothing] = List()
scala> List() >> List()
val res3: List[Nothing] = List()
scala> None >> 3.some
val res0: Option[Int] = None
scala> 3.some >> 4.some
val res1: Option[Int] = Some(4)
scala> 3.some >> None
val res2: Option[Nothing] = None
scala> None >> None
val res3: Option[Nothing] = None
Same as above, but using
the Scala Cats library:
import cats._
import cats.implicits._
26. MonadPlus and the guard Function
List comprehensions allow us to filter our output. For instance, we can filter a list of numbers to search only for numbers
whose digit contains a 7:
ghci> [x | x <- [1..50], '7' `elem` show x]
[7,17,27,37,47]
We apply show to x to turn our number into a string, and then we check if the character ‘7’ is part of that string. To see how
filtering in list comprehensions translates to the list monad, we need to check out the guard function and the MonadPlus type
class. The MonadPlus type class is for monads that can also act as monoids. Here is its definition:
class Monad m => MonadPlus m where
mzero :: ma
mplus :: ma -> ma -> ma
mzero is synonymous with mempty from the Monoid type class, and mplus corresponds to mappend. Because lists are monoids
as well as monads, they can be made an instance of this type class:
instance MonadPlus [] where
mzero = []
mplus = (++)
For lists, mzero represents a nondeterministic computation that has no results at all – a failed computation. mplus joins two
nondeterministic values into one. The guard function is defined like this:
guard :: Bool -> m ()
guard True = return ()
guard False = mzero
guard takes a Boolean value. If that value is True, guard takes a () and puts it in a minimal default context that succeeds. If
the Boolean value is False, guard makes a failed monadic value.
Miran Lipovača
27. Here it is in action:
ghci> guard (5 > 2) :: Maybe ()
Just ()
ghci> guard (1 > 2) :: Maybe ()
Nothing
ghci> guard (5 > 2) :: [()]
[()]
ghci> guard (1 > 2) :: [()]
[]
This looks interesting, but how is it useful? In the list monad, we use it to filter out nondeterministic computations:
ghci> [1..50] >>= (x -> guard ('7' `elem` show x) >> return x)
[7,17,27,37,47]
The result here is the same as the result of our previous list comprehension. How does guard achieve this? Let’s first see
how guard functions in conjunction with >>:
ghci> guard (5 > 2) >> return "cool" :: [String]
["cool"]
ghci> guard (1 > 2) >> return "cool" :: [String]
[]
If guard succeeds, the result contained within it is the empty tuple. So then we use >> to ignore the empty tuple and present
something else as the result. However, if guard fails, then so will the return later on, because feeding an empty list to a
function with >>= always results in an empty list. guard basically says, “If this Boolean is False, then produce a failure right
here. Otherwise, make a successful value that has a dummy result of () inside it.” All this does is to allow the computation to
continue.
Miran Lipovača
ghci> [x | x <- [1..50], '7' `elem` show x]
[7,17,27,37,47]
same result
28. for
queens <- placeQueens(k - 1)
queen <- 1 to n
if safe(queen, queens)
yield queen :: queens
placeQueens(k - 1) flatMap { queens =>
(1 to n) withFilter { queen =>
safe(queen, queens)
} map { queen =>
queen :: queens
}
}
do
queens <- placeQueens(k-1)
queen <- [1..n]
guard (safe queen queens)
return (queen:queens)
placeQueens(k-1) >>= queens ->
[1..n] >>= queen ->
guard (safe queen queens) >>
return (queen:queens)
Here we see the desugaring of the Scala for comprehension
again, but we also desugar the equivalent Haskell do expression.
Note how, while the desugared Scala code introduces the use of flatMap, withFilter and map, the desugared Haskell
code introduces the use of >>= (Haskell’s equivalent of flatMap) and >>.
Note also how, in Haskell, the guard function is used in both the do expression and in its desugared equivalent.
29. for
nums <- List(List(1,2),List(3,4))
num <- List(10,20)
if (num > 15)
yield num :: nums
List(List(1,2),List(3,4)) flatMap { nums =>
List(10,20) withFilter { num =>
num > 15
} map { num =>
num :: nums
}
}
do
nums <- [[1,2],[3,4]]
num <- [10,20]
guard (num > 15)
return (num:nums)
[[1,2],[3,4]] >>= nums ->
[10,20] >>= num ->
guard (num > 15) >>
return (num:nums)
[[20,1,2],[20,3,4]]
List(List(20, 1, 2), List(20, 3, 4))
Same as on the previous slide, except that here the logic
is simpler to understand and can be run at the REPL.
@philip_schwarz
30. do
nums <- [[1,2],[3,4]]
num <- [10,20]
guard (num > 15)
return (num:nums)
[[1,2],[3,4]] >>= nums ->
[10,20] >>= num ->
guard (num > 15) >>
return (num:nums)
List(List(20, 1, 2), List(20, 3, 4))
do
nums <- [[1,2],[3,4]]
num <- [10,20]
guard (True)
return (num:nums)
[[1,2],[3,4]] >>= nums ->
[10,20] >>= num ->
guard (True) >>
return (num:nums)
List(List(10, 1, 2), List(20, 1, 2), List(10, 3, 4), List(20, 3, 4))
do
nums <- [[1,2],[3,4]]
num <- [10,20]
guard (False)
return (num:nums)
[[1,2],[3,4]] >>= nums ->
[10,20] >>= num ->
guard (False) >>
return (num:nums)
List()
guard lets
through some
elements
guard lets
through all
elements
guard lets
through no
elements
31. ghci> [1,2] >>= n -> ['a',’b’] >>= ch -> return (n,ch)
[(1,'a'),(1,'b'),(2,'a'),(2,'b’)]
…
…
Here is the previous expression rewritten in do notation:
listOfTuples :: [(Int,Char)]
listOfTuples do
n <- [1,2]
ch <- [’a’,’b’]
return (n,ch)
Do Notation and List Comprehensions
Using lists with do notation might remind you of something you’ve seen before. For instance, check out the following piece
of code:
ghci> [(n, ch) | n <- [1,2], ch <- ['a','b’]]
[(1,'a'),(1,'b'),(2,'a'),(2,'b’)]
Yes, list comprehensions! In our do notation example, n became every result from [1,2]. For every such result, ch was
assigned a result from ['a','b’], and then the final line put (n,ch) into a default context (a singleton list) to present it as the
result without introducing any additional nondeterminism.
In this list comprehension, the same thing happened, but we didn’t need to write return at the end to present (n,ch) as the
result, because the output part of a list comprehension did that for us.
In fact, list comprehensions are just syntactic sugar for using lists as monads. In the end, list comprehensions and lists in
do notation translate to using >>= to do computations that feature nondeterminism. Miran Lipovača
32. do queens <- placeQueens(k-1)
queen <- [1..n]
guard (safe queen queens)
return (queen:queens)
[queen:queens |
queens <- placeQueens(k-1),
queen <- [1..n],
safe queen queens]
placeQueens(k-1) >>= queens ->
[1..n] >>= queen ->
guard (safe queen queens) >>
return (queen:queens)
We saw earlier what the Haskell do expression looks like when it is desugared.
Desugaring the list comprehension produces the same result.
33. queens n = placeQueens n
where
placeQueens 0 = [[]]
placeQueens k = [queen:queens |
queens <- placeQueens(k-1),
queen <- [1..n],
safe queen queens]
safe queen queens = all safe (zipWithRows queens)
where
safe (r,c) = c /= col && not (onDiagonal col row c r)
row = length queens
col = queen
onDiagonal row column otherRow otherColumn =
abs (row - otherRow) == abs (column - otherColumn)
zipWithRows queens = zip rowNumbers queens
where
rowCount = length queens
rowNumbers = [rowCount-1,rowCount-2..0]
def queens(n: Int): List[List[Int]] =
def placeQueens(k: Int): List[List[Int]] =
if k == 0
then List(List())
else
for
queens <- placeQueens(k - 1)
queen <- 1 to n
if safe(queen, queens)
yield queen :: queens
placeQueens(n)
def onDiagonal(row: Int, column: Int, otherRow: Int, otherColumn: Int) =
math.abs(row - otherRow) == math.abs(column - otherColumn)
def safe(queen: Int, queens: List[Int]): Boolean =
val (row, column) = (queens.length, queen)
val safe: ((Int,Int)) => Boolean = (nextRow, nextColumn) =>
column != nextColumn && !onDiagonal(column, row, nextColumn, nextRow)
zipWithRows(queens) forall safe
def zipWithRows(queens: List[Int]): Iterable[(Int,Int)] =
val rowCount = queens.length
val rowNumbers = rowCount - 1 to 0 by -1
rowNumbers zip queens
As a recap, let’s see again the translation of
the whole program from Scala to Haskell.
34. There is lots to do in part two. We’ll kick off by taking
the Scala version of the program, and extending it so
that it can display a single solution board as follows:
To conclude the first part of this slide deck,
see below for a simple way of displaying
the solutions to the N-queens problem.
We’ll then get the program to display,
all together, the results of queens(N)
for N = 4, 5, 6, 7, 8. Plus much more.
See you then.
@philip_schwarz