
Clojure and Project Euler, part 2
In a previous article ( Clojure and Project Euler, part 1 ), I described the solution to the first 3 tasks from the Euler project using clojure - a fairly young language, but with well-known parents.
In this article I will continue to acquaint the reader (and myself too) with this funny java lisp. And I will show you the solution of 3 more simple problems from Euler.
Task
Find the maximum product of 2 three-digit numbers, which is a palindrome.
Algorithm
1. Create a post of all the works.
2. Filter, leaving only palindromes.
3. Find the maximum.
Code
First, we determine the function determining whether the string is palindrome or not.
I decided to train willpower and try to write code with comments, at least f-tion.
It is worth noting 4 things.
1. The description of the function is written after its name and before the list of arguments. This description will be displayed when you call (doc your-function).
2. In clojure, all predicates (I understand them as functions from one variable that return true or false) usually end with a question mark.
3. Since Since we pass a number, we must convert it to a string first, this is done using the str function.
4. word is of type String, and (reverse word) returns a sequence already and with a simple comparison it will always be false. Therefore it is necessary to make a word out of word too. This is what we do with (seq word).
Now the main part:
C (reduce max ...) should be more or less clear, it just takes the maximum from the eight that it gets.
In (filter ...) we filter the number of numbers and leave only the palindromes, and immediately pass our predicate palindrom? There, rather than an anonymous function, as in the previous times.
More illustrative for example:
Task
Print the minimum number that is divided by all numbers from 1 to 20 inclusive. We take the
algorithm
and find the smallest common multiple of 20 numbers.
Code
Of course, you can write your NOC, but we won’t ... Better use ready-made functions, or rather libraries. Usually, clojure-contrib ( http://clojure.org/libraries ), which is an assembly of libraries written, as I understand it, by ordinary users, isconnected immediately with clojure. Clojure-contrib goes simply in the jar file and is included in the path along with clojure.jar. There are all sorts of different utilities. It can be noted that in the lazy-seq library there is a Fibonacci post and a prime number of primes, which we wrote in a previous article. But now we will be interested in the math library, in which there is the lcm function - NOC.
We connect:
And we decide:
I will skip some tasks that do not require any special new knowledge of the language, but only implementation. So go straight to 8:
The task
Given a number with 1000 characters and you need to find in it 5 consecutive digits that give the maximum product and print this product. You can see the number here: ( http://projecteuler.net/index.php?section=problems&id=8 )
Algorithm
1. First, you need to enter this number into the program, I decided to save it to a file and read from there, because I’m writing to its editor is not very convenient. At the same time, we will work with the libraries of Java itself.
2. Break the number into 5 groups of 5 digits.
3. Multiply and take the maximum.
Code
Number (20 lines of 50 characters each) is stored in input.txt
Here you can see the familiar BufferedReader and FileReader classes. You can create new class instances through the new function, in which the second parameter is the class name, third, fourth, etc. - arguments to the constructor of this class. It is worth noting that we can import a class so as not to write the full name, but we cannot import all classes from the package at once, as in Java. One by one.
You can call methods on an instance of the class through the dot: (.methodName instance arg1 arg2 ...).
We will write a method that will turn a string into a number of digits:
It is worth noting that static methods and Java class variables can be accessed through ClassName / methodName.
And now the main part:
Here the funny partition function is used, which returns the number of subsequences of a given number :)
In general, in our case, it divided the number of digits into one, the elements of which are groups of 5 digits, in increments of 1.
Here perhaps that's all for now. In the end, I would like to give a link to the website, which contains decisions on the portfolio of tasks from Euler, I unexpectedly stumbled upon myself. There really isn’t everything, but still you can see what options are available and learn, I think: http://clojure-euler.wikispaces.com/
In this article I will continue to acquaint the reader (and myself too) with this funny java lisp. And I will show you the solution of 3 more simple problems from Euler.
Task 4
Task
Find the maximum product of 2 three-digit numbers, which is a palindrome.
Algorithm
1. Create a post of all the works.
2. Filter, leaving only palindromes.
3. Find the maximum.
Code
First, we determine the function determining whether the string is palindrome or not.
I decided to train willpower and try to write code with comments, at least f-tion.
(defn palindrom?
"Returns true if x is palindrom,
false otherwise."
[x]
(let [s (str x)]
(= (seq s) (reverse s))))
It is worth noting 4 things.
1. The description of the function is written after its name and before the list of arguments. This description will be displayed when you call (doc your-function).
2. In clojure, all predicates (I understand them as functions from one variable that return true or false) usually end with a question mark.
3. Since Since we pass a number, we must convert it to a string first, this is done using the str function.
4. word is of type String, and (reverse word) returns a sequence already and with a simple comparison it will always be false. Therefore it is necessary to make a word out of word too. This is what we do with (seq word).
Now the main part:
(reduce max
(filter palindrom?
(for [i (range 100 1000) j (range i 1000)] (* i j))))
C (reduce max ...) should be more or less clear, it just takes the maximum from the eight that it gets.
In (filter ...) we filter the number of numbers and leave only the palindromes, and immediately pass our predicate palindrom? There, rather than an anonymous function, as in the previous times.
(for [i (range 100 1000) j (range i 1000)] (* i j))here the for-function is used, which returns a ct. It indicates local variables in brackets [], which are usually used in loops (I don’t know how to name them correctly, but I think everyone knows where i and j are used). Itself is formed from the values of the expression following the binding []. In our case, this is simply the product of i and j. There is still a slight improvement in the fact that j runs not from 100 to 1000, but from the current i, which speeds up the work.
More illustrative for example:
(for [i (range 1 5) j (range i 5)] [i j])
; We get the number of vectors: ([1 1] [1 2] [1 3] [1 4] [2 2] [2 3] [2 4] [3 3] [3 4] [4 4])
Task 5
Task
Print the minimum number that is divided by all numbers from 1 to 20 inclusive. We take the
algorithm
and find the smallest common multiple of 20 numbers.
Code
Of course, you can write your NOC, but we won’t ... Better use ready-made functions, or rather libraries. Usually, clojure-contrib ( http://clojure.org/libraries ), which is an assembly of libraries written, as I understand it, by ordinary users, isconnected immediately with clojure. Clojure-contrib goes simply in the jar file and is included in the path along with clojure.jar. There are all sorts of different utilities. It can be noted that in the lazy-seq library there is a Fibonacci post and a prime number of primes, which we wrote in a previous article. But now we will be interested in the math library, in which there is the lcm function - NOC.
We connect:
(use 'clojure.contrib.math)
And we decide:
(reduce lcm (range 1 21))
I will skip some tasks that do not require any special new knowledge of the language, but only implementation. So go straight to 8:
Task 8
The task
Given a number with 1000 characters and you need to find in it 5 consecutive digits that give the maximum product and print this product. You can see the number here: ( http://projecteuler.net/index.php?section=problems&id=8 )
Algorithm
1. First, you need to enter this number into the program, I decided to save it to a file and read from there, because I’m writing to its editor is not very convenient. At the same time, we will work with the libraries of Java itself.
2. Break the number into 5 groups of 5 digits.
3. Multiply and take the maximum.
Code
Number (20 lines of 50 characters each) is stored in input.txt
(def number
(let [reader (new java.io.BufferedReader (new java.io.FileReader "input.txt"))]
(reduce str (for [i (range 20)] (.readLine reader)))))
Here you can see the familiar BufferedReader and FileReader classes. You can create new class instances through the new function, in which the second parameter is the class name, third, fourth, etc. - arguments to the constructor of this class. It is worth noting that we can import a class so as not to write the full name, but we cannot import all classes from the package at once, as in Java. One by one.
You can call methods on an instance of the class through the dot: (.methodName instance arg1 arg2 ...).
We will write a method that will turn a string into a number of digits:
(defn to-digit-seq
"Converts string st
to sequence of digits."
[st]
(map # (Character / getNumericValue%) st))
It is worth noting that static methods and Java class variables can be accessed through ClassName / methodName.
And now the main part:
(reduce max
(map # (reduce *%)
(partition 5 1 (to-digit-seq number))))
Here the funny partition function is used, which returns the number of subsequences of a given number :)
In general, in our case, it divided the number of digits into one, the elements of which are groups of 5 digits, in increments of 1.
Here perhaps that's all for now. In the end, I would like to give a link to the website, which contains decisions on the portfolio of tasks from Euler, I unexpectedly stumbled upon myself. There really isn’t everything, but still you can see what options are available and learn, I think: http://clojure-euler.wikispaces.com/