2016년 11월 19일 토요일

[clojure-docs]sort, sort-by



sort, sort-by

딱 봐도, 정렬인 줄 알겠지?
(sort [5 4 3 2 6 1 3 4 2 6])
(1 2 2 3 3 4 4 5 6 6)
sort-by는 무언가 (다른 거)에 정렬이 되는 것
(sort-by count ["aaa" "bb" "c"])
("c" "bb" "aaa")

[clojure-docs]some



some

some은 처음에 나오는 함수가 참인 경우가 하나라고 있는지 물어보는 것이다.
(some #(> % 5) [1 2 3 4])
nil

(some #(> % 3) [1 2 3 4])
true
여기 나오는 값이 실제 값이 아닌 true인 것을 유의하자. 트릭으로 and를 쓰면 된다. (and가 매크로라서(?) 되는듯 나중에 더 공부하고 적어보기로 하겠다.)

2016년 11월 15일 화요일

[clojure-docs]filter



filter를 쓰면 참인 것만 추려내서 반환한다.
(filter #(< % 3) [1 2 3 4 5 6])
(1 2)
여기서 take-while과 filter의 차이는 무엇일까. take-while은 값이 정렬되어있으면 불필요한 자료를 검사하지 않고 결과 값을 반환한다. (정렬이 되어 있을 때는 take-while이 더 효율적인 듯 싶다.)

[clojure-docs]take-while



take-while

(def food-journal
  [{:month 1 :day 1 :human 5.3 :critter 2.3}
   {:month 1 :day 2 :human 5.1 :critter 2.0}
   {:month 2 :day 1 :human 4.9 :critter 2.1}
   {:month 2 :day 2 :human 5.0 :critter 2.5}
   {:month 3 :day 1 :human 4.2 :critter 3.3}
   {:month 3 :day 2 :human 4.0 :critter 3.8}
   {:month 4 :day 1 :human 3.7 :critter 3.9}
   {:month 4 :day 2 :human 3.7 :critter 3.6}])
take-while을 써서 특정 자료만 얻을 수 있다. 1,2월 자료만 가져온다.
(take-while #(< (:month %) 3) food-journal)
({:month 1, :day 1, :human 5.3, :critter 2.3} 
 {:month 1, :day 2, :human 5.1, :critter 2.0}
 {:month 2, :day 1, :human 4.9, :critter 2.1}
 {:month 2, :day 2, :human 5.0, :critter 2.5})
비슷한 drop-while이라는 것도 기억하자.
(drop-while #(< (:month %) 3) food-journal)
이 둘을 함께 써서 2월과 3월의 자료만 얻을 수 있다.
(take-while #(< (:month %) 4)
  (drop-while #(< (:month %) 2) food-journal))

[clojure-docs]take, drop



take

take는 두개의 인자를 받는다. 일단 한번 보자.
(take 2 [ 1 2 3 4 5])
(1 2)
drop 또한 두개의 인자를 받는다.
(drop 3 [1 2 3 4 5 6 7])
(5 6 7)
둘이 서로 비슷한 함수다.

2016년 11월 14일 월요일

[clojure-docs]reduce



reduce

process each element in a sequence and build a result(배열의 원소를 각각 처리)
(reduce + [1 2 3 4])
10
이 말은 이거와 같다.
(+ (+ 1 2) 3) 4)
끔찍하지 않은가?? 다음은 초기값을 지정하고 reduce를 실행하는 모습
(reduce + 100 [1 2 3 4])

2016년 11월 13일 일요일

[clojure-docs]loop



loop

이것도 말그대로 loop문을 만드는 것이다. 하지만 우리가 생각하는 index를 가지고 for문을 도는 것이 아니라. 재귀를 한다. 한번 어떻게 되는건지 보자.
(loop [x 10]
  (when (> x 0)
    (println x)
    (recur (- x 1))))
10
9
8
7
6
5
4
3
2
1
nil
위의 예제는 x=10이 초기값으로 시작한다. recur는 재귀를 실행한다.

[clojure-docs]zipmap



zipmap

값을 연결해서 맵을 만들어 준다.
(zipmap [:a :b :c :d] [1 2 3 4 5])
{:a 1, :b 2, :c 3, :d 4}
그럼 map이랑 차이는 뭘까? map은 함수를 계속 실행시킨다. 그 값을 리스트로 반환한다.
덧붙여서 다른 질문들을 둘러보자.
zipmap, map vector의 차이를 찾고 있다.
(zipmap [:k1 :k2 :k3] [10 20 40])
=> {:k3 40, :k2 20, :k1 10}

(map vector [1 2 3] [4 5 6] [7 8 9])
=> ([1 4 7] [2 5 8] [3 6 9])
스택오버플로우에서는 그 차이를 이렇게 말한다.
Use (zipmap ...) when you want to directly construct a hashmap from seperate of keys and values. The output is a hashmap.
Use (map vector...) when you are trying to merge multiple sequences, The output is a lazy sequence of vectors.

[clojure-docs]dotimes



dotimes

말그대로 여러번 계속 실행하도록 하는 것.
(dotimes [n 5] (println "n is" n))
n is 0
n is 1
n is 2
n is 3
n is 4
nil

[clojureapi]juxt



juxt

juxtaposition : 병렬, 병치, 나란히 놓기 api doc에 잘 설명되어 있다. juxt 안에 있는 함수들을 나란히 놓는 것이다. ((juxt a b c) x) => [(a x) (b x) (c x)]
((juxt :a :b) {:a 1 :b 3333 :c 3234 :d 234})
[1 3333]
왜 이렇게 나오는 걸까 이유는
[(:a {:a 1 :b 3333 :c 3234 :d 234}) (:b {:a 1 :b 3333 :c 3234 :d 234})]
이렇게 각각 함수(:a :b)를 호출하는 것이다.

[clojureapi]doseq




doseq

body의 내용을 각각 실행시킨다. api에 적혀있는 예제를 보면
(doseq [x [-1 0 1]
        y [1  2 3]] 
  (prn (* x y)))
-1
-2
-3
0
0
0
1
2
3
nil
이렇게 각 벡터를 x,y라 하고 각각 계산한다. 총 값을 9개가 나온다.

[Mathematics for Computer Science][Division Algorithm] 스터디 07

The Division Algorithm

If one number does not evenly divide another, then there is a remainder" left over. More precisely, if you divide n by d, then you get a quotient q and a remainder r.
어떤 수가 나누어지지 않을 때 (즉 소수일 때?) 그 수는 나머지를 가진다. 그리고 몫도 알 수 있다. 이 말은 y = ax + b가 된다는 말.

Theorem 25 (Devision Algorithm)

Let n and d be integers such that d less than 0. Then there exists a unique pair of integers q and r such that n = qd + r and 0 ≤ r  less than d. 위의 y = ax + b와 비슷한 말이다. 여기서 문제는 저 여기서 a와 b의 조합이 단 하나라는 점이다. 어째서 그러한 지 보자. Proof. We must prove that the integers q and r exist and that they are unique.
For existence, we use the well-ordering principle. Fisrt, we show that the equation n = qd + r holds for some r ≥ 0. If n is positive, then the equation holds when q = 0 and r = n. If n is not positive, then the equation holds when q = n and r = n(1-d) ≥ 0. Thus, by well-ordering principle, there must exist a smallest r ≥ 0 such that the equation holds. Furthermore, r mush be less than d; otherwise, b = (q +1)d + (r-d) would be another solution with a smaller nonnegative remainder, contradicting the choice of r.
Well-ordering Principle 자연수의 정렬성 - 공집합이 아닌 모든 자연수 집합의 부분집합은 하나의 최소 정수를 포함한다는 정리 S is subset of T ∀S such that S ⊆ ℕ and S not equals∅,∃a ∈ S such that a ≤ b for all b ∈ S
즉, 최소항이 존재한다는 말 자연수 1 2 3 4 ... (공집합이 아닌 부분집합을 생각하라) 예를 들어 1.5보다 큰 자연수의 집합 -> 최소항 '2'가 존재한다.
Now we show uniqueness. Suppose that there exist two diffent pairs of integers q1, r1 and q2, x2 such that:

n = q1d + r1 (where 0 ≤ r1 less than d)
n = q2d + r2 (where 0 ≤ r2 less than d)

Subtracting the second equation from the first gives:

0 = q1 - q2d + (r1 - r2)
자연수의 정렬성(well-ordering principle)에 의하면 무조건 0보다 크거나 같은 r이 존재한다.(음수건 양수건) 그리고 r은 d보다 작아야 한다. (당연하지 나머지니까) 만약 아니면 값이 엄청 많아진다. 유니크하지 않다는 것! 유니크하다는 것을 말해주기 위해 같은 값에 두개의 조합이 있다고 가정하는 것이다. (바로 위에 만든 것처럼)
The absolute difference between the remainders r1 and r2 must be less than d, since 0 ≤ r1, r2 less thand. This implies that the absolute value of (q1 - q2)d must also be less than d, which means that q1 - q2 = 0. But then the equation above implies that r1 - r2 = 0 as well. Therefore, the pairs q1, r1 and q2, r2 are actually the same, which is a contradiction. So the quotient and remainder are unique.
나머지의 차는 d보다 작아야 한다.(r1,r2의 조건을 보라) 나머지가 d만큼 차이가 나지 않으니까 (q1 - q2)d 또한 0보다 작아야 한다. 이러면 어쩔 수 없이 저 값은 0 이 된다. 그리고 나머지의 차도 0이 된다. 둘은 같은 값인 것이고, 이것은 모순이 된다.(왜냐하면 처음에 두개의 조합을 가정했다.)

[누구나 쉽게 배우는 클로저] [함수(function)][destructuring] study 10




DESTRUCTURING


DESTRUCTURING은 집합에서 이름에 간단히 값을 매기기 위한 아이디어를 바탕으로 한다.

(defn my-first
  [[first-thing-in-vector]]
  first-thing-in-vector)
(my-first [1 2 3 4 5 6])
1

my-first 안에 들어있는 인자가 벡터로 되어있는 것을 보자. "이 인자는 벡터!"라는 것을 말해주는 것이다. 이 벡터안에 있는 것들을 마음데로 이름 붙이고 또 나머지 매개변수도 쓸 수 있다.

(defn students
  [[first second & others]]
  (print (str "첫 번째 학생: " first))
  (print (str ", 두 번째 학생: " second))
  (print (str ", 나머지 학생: " (clojure.string/join ", " others))))

(students ["Kim" "Min" "Nam" "Hwang" "Ku"])

이번에는 벡터가 아닌 맵으로 해보자. 맵에 있는 내용과 나의 매게변수와 연결을 할 수 있는데 자세한 것은 밑에서 구경해보자.
(defn coordinate
  [{x :x-axis y :y-axis}]
    (println (str "x축: " x))
    (println (str "y축: " y)))
(coordinate {:x-axis 24 :y-axis 44})
더 간결하게
(defn coordinate
  [:keys {x-axis y-axis}]
  (println (str "x축: " x-axis))
  (println (str "y축: " y-axis)))
:as를 사용하여 원래의 맵에 접근할 수 있다.
(defn coordinate
  [:keys [x-axis y-axis] :as args}]
  (println (str "x축: " x-axis))
  (println (str "y축: " y-axis)))