2018년 2월 17일 토요일

[리뷰] 파이썬을 좋아하면 누구나 읽어보아야할 [Head First Python]


아주 좋은 책이다.

잘 짜여진 이야기를 풀어나가는 것처럼 술술 나아간다. 분명 이렇게 만들기 위해 여러번 고쳐썼을 것이다.

헤드퍼스트 특유의 만담은 파이썬을 더 잘 이해하게 해주고

setuptools를 사용하여 간단한 모듈을 만들어보는 것도 멋졌다.

python의 깊은 내용은 알 수 없었지만, 파이썬을 만나볼 수 있었다.

책을 다보면 나도모르게 web개발을 할 수 있을 정도의 연결고리를 만들어준다.

알게모르게 배워야 하는 것들을 다 배운 것 같다.

파이썬에 대해 알고 싶은 사람들은 다른 책보다
일단 헤드퍼스트 파이썬을 먼저 만나서
파이썬이 무엇인지 파이썬이 무엇을 추구하는지
알아보고 다른 정보들을 접하기를 추천한다.

Head First Python URL : http://www.hanbit.co.kr/store/books/look.php?p_code=B1306099216

2018년 2월 8일 목요일

[python][algospot] 울타리 잘라내기

구종만의 알고리즘 문제해결 책을 본 후 파이썬으로 짜봤다.
def brute_force(h):
    ret = 0
    N = len(h)
    for left in range(N):
        minHeight = h[left]
        for right in range(left, N):
            minHeight = min(minHeight, h[right])
            ret = max(minHeight*(right-left+1), ret)
    return ret

print(brute_force([7,1,5,9,6,7,3]))
print(brute_force([1,4,4,4,4,1,1]))

def divide_conquer(h):
    def solve(left, right):
        if left == right: return h[left]

        # 이 둘이 중요.
        mid = (left + right) // 2  # divide
        ret = max(solve(left, mid), solve(mid+1, right))  # divide and conquer

        lo , hi = mid, mid+1  # 중앙에 걸치는 녀석들을 잡기 위해
        height = min(h[lo], h[hi])  # 중앙에서 낮은 판자높이를 구함. (초기값)
        ret = max(ret, height*2)  # [mid,mid+1]만 포함하는 너비 2인 사각형 고려

        # 후처리작업 병합정렬처럼 반으로 잘라서 각개격파를 했지만
        # 병합정렬과는 다르지만 부족한 면을 반복문으로 메꾸는 것.
        # 사각형이 입력 전체를 덮을 때까지 확장한다.
        while (left < lo or hi < right):
            # 더 높은 판자를 향해 확장한다. (낮은 판자로 가면 최대값을 구할 수 없다.)
            if (hi < right and (lo == left or h[lo-1] < h[hi+1])):
                hi += 1
                height = min(height, h[hi])
            else:
                lo -= 1
                height = min(height, h[lo])
            ret = max(ret, height*(hi-lo+1))

        return ret
    return solve(0, len(h)-1)


print('divide_conquer')
print(divide_conquer([7,1,5,9,6,7,3]))
print(divide_conquer([1,4,4,4,4,1,1]))

[python][hackerrank] Jumping on the Clouds: Revisited

아직은 역시 웜업 단계인가 보다.
쉽다.
n, k = tuple(map(int, input().strip().split(' ')))
c = tuple(map(int, input().strip().split(' ')))

result = 100
tmp = 0

while True:
    tmp = (tmp + k) % n
    result -= (1 + c[tmp]*2)
    if tmp == 0:
        break
    
print(result)

2018년 2월 6일 화요일

[python][hackerrank] Sequence Equation

처음에는 리스트로 그냥 뿌려서 하면 되는 건가 했는데
해(OUTPUT)를 가지고 반대로 x값(INPUT)을 구하는 것이었다.
값이 없는 경우가 있다면 그것들을 어떻게 해야 하는지 설명이 필요한데 그에 대한 설명이 없어서
그런경우는 없다는 가정하에 문제를 풀었다.

그래서 미리 p(p(y))를 풀어서 key값에 넣고 그 안에 x(INPUT)값을 value로 넣었다.

n =  int(input())
n_list = list(map(int, input().strip().split(' ')))
p = { n_list[n_list[x-1]-1]:x for x in n_list}

for i in range(1, n+1):
    print(p[i])

[python][hackerrank] Circular Array Rotation

n은 배열 값의 수
k는 right-circular-rotation의 횟수
q는 질의 회수
m은 실제 배열의 값

from collections import deque

n, k, q = map(int, input().strip().split(' '))
m = deque(map(int, input().strip().split(' ')))  # integers
m.rotate(k)  # wow...

for m_i in range(q):
    print(m[int(input())])  # don't need strip(). int() will do this.

혹은 다른 방법을 사용해보자.

n, k, q = map(int, input().strip().split(' '))
m = list(map(int, input().strip().split(' ')))

k %= n; tmp = m[-k:]; del m[-k:]; m[0:0] = tmp

for m_i in range(q):
    print(m[int(input())])  # don't need strip(). int() will do this.

[clojure][designpattern] 프로토타입 패턴

프로토타입은 원형틀이라고도 볼 수 있다.
기본적으로 만들어진 틀을 사용하는 것이다.
내용에서는 회원등록양식을 사용했는데 그 틀에 대한 기본틀을 프로토타입이라 하자. 여기서는 몸무게를 적지 않으면 60킬로를 기본값으로 넣는다고 한다.
그리고 중요한 것은 clone()메소드인데 왜 중요하냐면 기존에 만들어진 틀을 아주 쉽게 복사할 수 있는 것이다.

public class RegistrationForm implements Cloneable {
  private String name = "Zed";
  private String email = "zzzed@gmail.com";
  private Date dateOfBirth = new Date(1990, 1, 28);
  private int weight = 60;
  private Gender gender = Gender.MALE;
  private Status status = Status.SINGLE;
  private List children = Arrays.asList(new Child(Gender.FEMALE));
  private double monthSalary = 1000;
  private List favouriteBrands = Arrays.asList("Adidas", "GAP");

  @Override
  protected RegistrationForm clone() throws CloneNotSupportedException {
    RegistrationFrom prototyped = new RegistrationForm();
    prototyped.name = name;
    prototyped.email = email;
    prototyped.dateOfBirth = (Date)dateOfBirth.clone();
    prototyped.weight = weight;
    prototyped.gender = gender
    prototyped.status = status;

    List childrenCopy = new ArrayList();
    for (Child c : children) {
      childrenCopy.add(c.clone());
    }
    prototyped.children = childrenCopy;
    prototyped.monthsCopy = monthSalary;

    List brandsCopy = new ArrayList();
    for (String s : favoriteBrands) {
      brandsCopy.add(s);
    }
    prototyped.favouriteBrands = brandsCopy;
    
    return prototyped;
  }
}
사용자를 만들 때마다, clone()을 호출해서 기본값으로 쓴다.
왜 clone()을 사용해야 하나? 바로 자바가 나를 죽어라 헷갈리게 한 내용인 카피 문제이다.
이것 때문에 나는 getter를 만들때도 그것이 객체라면 복사를 한다. (혹시 몰라서...)


Clojure

(def registration-prototype
  {:name "Zed"
   :email "zzzed@gmail.com"
   :date-of-birth "1970-01-01"
   :weight 60
   :gender :male
   :status :single
   :children [{:gender :female}]
   :month-solary 1000
   :brands ["Adidas" "GAP"]})

;;return new object
(assoc registration-prototype
  :name "WHO"
  :email "EMAIL@DOTCOM"
  :weight 52
  :gender :female
  :month-salary 0)
clojure는 기본적으로 불변객체이기 때문에 clone은 필요없다.
그렇다면 항상 다 모든것을 final로 만들어 복사하면 느려지지 않을까?
느리긴 한데... 아주 느리지는 않다는 것이 클로저들의 주장인 것같다.

[python][hackerrank] Save the Prisoner!

#!/bin/python3
def saveThePrisoner(n, m, s):
    res = (m + s - 1) % n
    if res == 0:
        res = n
    return res

t = int(input().strip())
for _ in range(t):
    n, m, s = [int(x) for x in input().strip().split(' ')]
    result = saveThePrisoner(n, m, s)
    print(result)

[python][hackerrank] Viral Advertising

좀 더 단순하게 풀 수는 없었을까?
날짜가 지나갈 때마다 생존하는 녀석들을 따로 기억해야했고
그거와 별개로 내가 뱉어내야할 결과값을 따로 담아야했다.
def viral_ad(n):
    tmp = 2
    res = 2
    while n > 1:
        tmp = (tmp * 3) // 2
        res += tmp
        n -= 1
    return res

n = int(input().strip())
result = viral_ad(n)
print(result)

2018년 2월 3일 토요일

[python][hackerrank] Beautiful Days at the Movies

일반적인 방법
i,j,k = [int(x) for x in input().strip().split(' ')]
cnt = 0
for n in range(i,j):
    diff = abs(n - int(str(n)[::-1])) % k
    if diff == 0:
        cnt += 1
print(cnt)

조금더 일반적인(?) 방법
def bueatiful_days2():
    i,j,k = [int(x) for x in input().strip().split(' ')]
    res = sum(1 for x in range(i,j) if abs(int(str(x)[::-1])-x) % k == 0)
    print(res)

[python][hackerrank] Utopian Tree

법칙을 찾는데 오래 걸렸다. easy인데 푸는데 너무 시간이 걸렸다. 리듀스 같은걸 쓰려고 고집해서 그런것 같기도 하다.
n res
0 1 = 1
1 1*2 = 2
2 1*2 + 1 = 3
3 (1*2 + 1) * 2 = 6
4 (1*2 + 1) * 2 + 1 = 7
5 14
6 15
7 30
8 31
even
2 3 2*1 + 1 -> 11
4 7 2*2 + 2*1 + 1 -> 111
6 15 2*2*2 + 2*2 + 2*1 + 1 -> 1111
8 31 2^4 2^3 2^2 2^1 +2^0 -> 11111
from functools import reduce

t = int(input().strip())

for _ in range(t):
    n = int(input().strip())
    print(reduce(lambda a,b: a+b, (map(lambda x: pow(2,x), range(((n+1)//2)+1)))) - n%2)

좀더설명하자면
n은
2일때 11
4일때 111
6일때 1111
8일때 11111
각각 1의 갯수만큼 이진수가 필요하다.
ex) n = 4
111 -> range(((4+1)// 2)+1) -> range(2+1) -> 1 2 3
저절로 1 2 3 이라고 나와주니 더 고맙다. 바로 pow를 이용해서 값을 구하자
[pow(2,1), pow(2,2), pow(2,3)]
그리고 다 더한다. reduce로
reduce(lambda a,b: a+b, [pow(2,1), pow(2,2), pow(2,3)])
그리고 even odd에 따른 차이를 뒤에 붙여준다.
 - n%2


[python][hackerrank] Designer PDF Viewer

#!/bin/python3
import string
from functools import reduce

h = {key: int(value) for key, value in zip(string.ascii_lowercase, input().strip().split(' '))}
word = input().strip()

height = reduce(max, map(lambda x: h[x], word))


print(len(word)*height)

참고자료: 딕셔너리로 한꺼번에 가져오기 위한 자료.
https://stackoverflow.com/questions/16060899/alphabet-range-python

[python][hackerrank] The Hurdle Race

이렇게 풀었다.
https://www.hackerrank.com/challenges/the-hurdle-race/problem
#!/bin/python3

n, k = [int(x) for x in input().strip().split(' ')]
height = [int(x) for x in input().strip().split(' ')]


print((lambda x: x if x > 0 else 0)(max(height)-k))
음... 나쁘지 않은듯. 결국 인풋을 받는 내용을 빼고는 한줄로 끝낸 거니까... 근대 이게 효율적인건가?