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 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/

    Also popular now: