[작성자:] snowall

  • 로또번호 추천기


    페이스북 생활코딩에서 봤다.

    45개중 6개의 번호를 알려주는 알고리즘을 생각해 보자.

    1. 6개의 빈칸을 만든다.

    2. 6개의 칸 중 가장 처음 만난 빈칸에 1~45사이의 임의의 정수를 넣는다.

    3. 6개의 칸에 중복된 것들이 있나 없나 검사하고, 중복된 것이 있으면 지운다.

    4. 2번으로 돌아가서 반복. 6개의 칸이 모두 차 있으면 종료.

    가장 간단한 알고리즘인데 2중 반복구문을 써야 하니까 아무래도 효율성이 떨어지지 싶다.

    여기에 내가 제안한 알고리즘은 다음과 같다.

    0. 1부터 45중 6개를 골라서 만들 수 있는 모든 패턴을 미리 생성해서 기록한다. 이건 26!과는 달리 약 100메가바이트 정도의 작은 용량을 차지하므로 미리 해둘 수 있다. 이 때 기록에 인덱스를 만드는데, 1부터 8145060이 적당할 것이다.

    1. 1부터 8145060사이의 임의의 정수를 선택한다.

    2. 선택된 정수에 해당하는 인덱스로 찾아가서 로또 번호를 고르면 된다.

    이건 저장공간이 많이 필요해서 그렇지 일단 계산만 해두면 상수시간 내에 계산할 수 있는 알고리즘이 된다.

    저장공간이 필요하지도 않은 매우 간단한 알고리즘이 있는데, 다음과 같다.

    1. “2, 11, 21, 31, 41, 43″을 출력한다.

    로또 번호는 뭘 고르더라도 당첨될 확률이 같으므로, 굳이 프로그램에서 난수를 생성할 필요 없이 로또 추첨을 기다리면 추첨할 때 난수가 생성되므로 알고리즘이 매우 간단해진다.


    (https://kldp.org/node/118661

    왜 그런지는 이 글을 참고바람.)

    장난치지 말고 1~n의 정수중에서 k개를 겹치지 않게 선택해주는 그럴듯한 알고리즘을 만들어달라고 한다면 다음과 같다.

    1. k개의 빈칸을 만든다.

    2. 1과 n-k 사이에 있는 임의의 정수를 선택한다. 이것이 첫번째 수이고, n1이라고 하자.

    3. (n1)+1과 n-k+1 사이에 있는 임의의 정수를 선택한다. 이것이 두번째 수이고 n2라고 한다.

    이걸 k번 반복한다.

    이 알고리즘은 결과물을 심지어 정렬된 상태로 출력시켜준다.

    이런 알고리즘도 가능하다.

    1. 1~7사이의 정수를 하나 선택한다. x라고 하자.

    2. i=1~6까지 반복하여 i*x를 출력한다.

    어차피 로또는 뭘 골라도 그게 그거라 별로 의미는 없다.

  • 천재 주머니

    대학원 동기가 이런 얘기를 했다. “호주머니는 인간보다 똑똑하다. 왜냐하면 이어폰 끈이 인간으로서는 도저히 상상할 수 없는 방법으로 꼬여있기 때문이다.”


    http://www.29sfilm.com/2012/Sub_ContestFilmView.aspx?movieidx=1585612

    이어폰 줄이 꼬여있다는 것으로 영화도 만들 수 있다.


    http://www.todayhumor.co.kr/board/view.php?table=humordata&no=960879

    이어폰 줄이 꼬이는 것에 관한 설명1


    http://pgr21.com/pb/view.php?id=bug&no=136893

    과연 열역학 제 2법칙 때문일까?


    예전에 주머니 속에 있는 밧줄이 왜 저절로 꼬이는지 연구한 논문이 발표되었다는 기사를 봤는데 어디서 봤는지 찾을 수가 없다.

    DSmithKnotting.pdf에 액세스하려면 클릭하세요.


    그 논문을 찾았다.




    오유에서 찾아줌.http://www.todayhumor.co.kr/board/view.php?table=jisik&no=110037


    http://blog.naver.com/PostView.nhn?blogId=fishingholic&logNo=60055939284

    무려, 물리학 부문에서 이그노벨상을 받은 연구다.

    논문 리뷰는 시험 끝나고 읽어본 다음에


    http://comic.naver.com/webtoon/detail.nhn?titleId=471283&no=151

    만화 소재로도 등장.

  • 윈도우즈 8.1

    차라리 윈도우즈 8이 낫다.

    아니 그냥 윈도우즈 7을 쓰거나 리눅스를 쓰는게 낫다.

    내 관점에서 볼 때, 인터넷뱅킹과 아래한글이 작동한다는 것 외에 별다른 장점이 없다.

  • Gravity

    친구의 유혹으로 영화 그래비티를 봤다.

    3차원 아이맥스로 봐서 16000원이 들었다.

    16000원의 가격이 적절하다는 점은 동의하지만, 재미가 없는건 아닌데 묘하게 돈이 아깝다.

    영화를 본건지 다큐멘터리를 본건지 혼란스러운.

    배우 딱 2명 나온다. 배우보다 성우가 더 많이 출연한 영화랄까. 나머지 인물은 그냥 시신으로 찬조출연. 초반에 엑스트라 한명 빼고.

    안방극장 화질 테스트 하실 분은 필히 소장.

  • Transition of Proton Energy Scaling Using an Ultrathin Target Irradiated by Linearly Polarized Femtosecond Laser Pulses


    http://arxiv.org/abs/1304.0333

    선편광된 극초단 페타와트 레이저의 복사압을 이용한 양성자 가속방법에 관한 논문이다.

    아마 광주에서 한 일로 나오는 마지막 논문이 될 듯.

    이걸 PRA에 냈다고 했는지 PRL에 냈다고 했는지 Nature에 냈다고 했는지가 잘 기억이 안 난다. 알게 되면 추가해야겠다.

    저자의 기여분에서 내가 한 일이 실험 수행으로 되어 있는데, 사실은 양성자 에너지 분석도 했다. 논문에는 안써줬지만. -_-;


    내년부터는 비선형광학 연구로 논문을 내 보자.

    PRL에 나왔음.

    PRL 111, 165003 (2013)

    “Transition of Proton Energy Scaling Using an Ultrathin Target Irradiated

    by Linearly Polarized Femtosecond Laser Pulses”


    http://prl.aps.org/abstract/PRL/v111/i16/e165003


    PRL에는 arXiv에 올릴때와 다른 제목으로 출판되었다.

  • 수치해석 16 – Monte Carlo integration

    적분을 수행하는데 여러가지 방법이 있지만, 어떻게 해야 할지 정말 모르겠다면 몬테 카를로 방법이 있다.

    몬테 카를로 방법은 단순히 면적을 계산하는 방법인데 알고리즘은 다음과 같다.

    1. 난수 (x, y)를 생성한다.

    2. f(x)>y이면 카운트를 +1한다.

    3. N번 반복한 후

    4. 카운트를 N으로 나누면 적분값이다.

    x의 범위는 적분 구간, y의 범위는 f(x)가 해당 적분 구간에서 갖게 되는 최대값과 0 사이의 영역이다.

    잘 보면 알겠지만, y가 f(x)와 0으로 둘러싸인 구간에, 임의로 점을 뿌리는 과정이다.

    점을 다 뿌린 후, 뿌린 수 중에 몇개나 구간 안에 들어갔는지 갯수를 센다. 그럼, 해당 함수로 둘러싸인 영역 안에 들어갈 확률은 영역의 넓이에 비례하므로, 뿌린 수 대비 들어간 수의 비율을 계산하면 된다.

    실제 코드는 다음과 같다.

    import random as rd

    import numpy as np

    import os

    fun = lambda x:np.sqrt(1.-x*x)

    xA = 0. # x의 구간 시작

    xB = 1. # y의 구간 끝

    yA = 0. # f(x)의 최소값

    yB = 2. # f(x)의 최대값보다 큰 임의의 값. 클수록 정확해지고 작을수록 빨라진다. f(x)의 최대값보다 같지 않고 더 큰 수를 넣어야 한다.

    AREA = np.abs((xA-xB)*(yA-yB)) # 구간으로 둘러싸인 영역의 넓이.

    rd.seed(os.times())

    it = 1000

    savefile = open(“circle.txt”, “w”)



    counted = 0




    for i in range (it):



    if fun(rd.uniform(xA, xB)) > rd.uniform(yA, yB): counted+=1


    print str(it)+” iteration, “+str(


    AREA*float(counted)/(float(it))


    )+” is integration result.”)

    빨간색으로 색칠한 부분이 “핵심코드”이다. 너무 짧은거 아니냐고 물어볼수도 있지만, 진짜로 저게 끝이다.

    여기서, 함수 안에 들어간 경우의 수를 반복한 횟수로 나눠준 다음 왜 면적을 곱해주는 걸까? 생각해 봅시다.



    0부터 1까지 Sqrt(1-x*x)를 적분한 결과. 가로축은 반복 횟수인데, 백만번정도 반복한 것까지 그렸다. 잘 보면 정확히 pi/4에 수렴하는 것을 관찰할 수 있다.

    아무생각없이 짜도 잘 굴러가는 굉장히 아름다운 알고리즘이다.

    문제는 f(x)가 음수인 경우에는 아무생각없이 짜면 안되고 생각은 한번 해줘야 한다는 점.

    임의의 N차원에서 수행하는 다중적분인 경우에는 난수를 생성하는 구간을 “잘” 잡거나, 또는! 그냥 “충분히 큰” 초직다면체(hyper-rectangular)에 해당하는 난수를 생성한 후 갯수를 셀까 말까 카운트하는 판정 루틴에 f(x)보다 작아야 한다는 조건 뿐만 아니라 “내가 원하는 구간 안에 들어가야 함”까지 조건을 넣으면 된다. 물론 그게 그거겠지만, 여기서는 단순히 “안에 있는가 없는가”만 판단하면 되기 때문에 그냥 다중적분보다는 쉽다.

    다시말해서,


    내가 어디에서 뭘 적분하는지만 알고 있으면


    수치적인 해를 구할 수 있다는 뜻이다.

    여담

    (=개드립)

    인데.

    인생은 내가 어디서 뭘 해야 하는지 알지도 못할 뿐만 아니라, Monte carlo 방법을 쓴답시고 도박하다간 망한다. 수치해석적 인생은 수치스러운 인생으로 귀결된다.

  • 과학자의 이직


    http://news.naver.com/main/read.nhn?mode=LSD&mid=shm&sid1=105&oid=092&aid=0002037062

    소속 과학자의 이직 때문에 정보 유출이 걱정된다면 돈을 더주고 붙잡아야겠지.

    부득이하게 이직해야 하는 경우에도 정보 보안 부분에 대해서 보상을 하고 유출시에 배상청구를 하는 것이 올바르다.

    그리고 전 직장에서 얻은 노하우를 어떻게 이번 직장에서 안 쓰지?

    예를 들어 광섬유 가공을 기가막히게 하는 방법을 아는 장인이 있는데, 한 연구소에서 다른 연구소로 영입해갔다면, 이 장인은 그 가공법을 처음부터 다시 개발해야 하나?

  • 개구리 들어간 분유통 문제의 결론

    얼마 전 분유에서 개구리가 발견되었다는 소식이 있었다.


    http://snowall.tistory.com/3372




    http://news.naver.com/main/read.nhn?mode=LSD&mid=sec&sid1=102&oid=277&aid=0003105030


    http://view.asiae.co.kr/news/view.htm?idxno=2013101410211958035

    민원을 담당하는 행정부에서는 개구리가 제조 단계에서 들어가지 않았다는 결론을 내렸다. 이 결론이 진짜로 완벽히 증명되었는지는 모르겠으나 소비자가 유사한 급의
    연구소에 의뢰해서 반박하는 실험결과를 내지 않는 한 믿을만한 사실이다. 연구소가 회사의 돈을 받고 실험한것이니 결과를 조작했을수도
    있다고 생각하는 사람들은 분유 사다가 직접 실험해 보기를 바란다. ‘과학’은 누가 결론을 냈던지, 누구든 반복실험하면 같은
    결과를 얻을 수 있는 사실을 이야기하도록 하고 있고 여기서 구라치다 걸리면 직장에서 짤린다. 고려대 나자현 교수님이 그런걸 모르는
    분도 아닐 테고, 이정도 일로 직장을 걸고 구라를 칠 정도로 남양으로부터 큰 돈을 받지도 않았을테니 저 실험 결과는 믿을만하고, 실험 결과를 바탕으로 보면 제조단계에서 개구리가 들어가지 않았다는 사실은 상당한 정도로 믿을만하다.

    개구리가 제조 단계에서 들어가지 않았다는 결론을 믿긴 믿겠는데, 그렇다고 소비자의 문제제기가 부당하거나 블랙컨슈머라고 폄하되어서는 안된다.


    소비자는 제품에 문제가 있다고 주장했다. 이 과정에서 제품에 문제가 있음을 소비자가 증명하지 못하고, 제조사가 제품에 문제가 없음을 증명했다. 이 과정은 매우 중요하다. 제품 문제 때문에 목숨을 걸어야 하는 자동차 급발진이나 에어백 불량 문제를 생각해 보자. 우리나라에서는 소비자가 제품의 문제임을 증명해야 한다. 하지만 자동차와 같이 복잡한 제품의 경우 소비자가 제품의 결함을 찾아내기는 매우 어려운 일이다. 자동차의 전문가는 자동차 제조사인데 우리나라에서는 대체로 소비자가 제품의 결함을 증명해야 하고, 그렇게 하지 못하면 손해 배상을 받을 수 없다.

    자동차 제조사의 입장에서, 그리고 어떻든 상품을 만드는 업자의 입장에서 보면, 제품에 문제가 있다고 불만을 터트리는 소비자들은 반갑지 않을 것이다. 그러나 그런 소비자들이 반박할 수 없도록, 위의 남양 유업과 마찬가지로, 과학적인 실험과 근거를 통해서 반박한다면 그런 소비자들은 차츰 사라질 것이다. 제품에 결함이 없음을 증명하는 과정에서 비용이 들어갈 것이고 그것이 제품의 제조비용을 상승시켜 이익률을 갉아먹을 것이라고 하더라도 믿을 수 있는 제품을 만드는 것이 결국은 최고의 마케팅이자 최상의 전략이다. 그렇다면, 우리나라에서 소비자들이 문제제기를 했을 때 적극적으로 문제를 합리적으로 과학적으로 결론짓는 것이 좋다. 또한, 과학적으로 증명을 한번 해 두면 더 분명하고 자세하게 반박하는 증거가 나오지 않는 한 유사한 사례들은 한번에 기각된다. 지금처럼 불평불만이 가득한 상태에서 서로 욕하고 있는 것은 모두에게 바람직하지 않은 상황이다.

    다시한번 말하지만, 소비자의 문제제기는 합당했고 제조사는 비용을 들여서 무죄를 증명했다. 이것이 바로 ‘합리적’인 것이다.

  • 26!

    어떤 분이 A에서 Z까지 모든 알파벳 26자로 이루어진 모든 경우의 수를 출력하는 프로그램을 만들 수 없느냐고 문의해서 “안돼요”라고 답을 보냈다.

    일단 26!은 1부터 26까지 모두 곱한 수이다. !은 굉장히 빨리 커지는 함수인데, 4!이나 5!정도를 생각하고서 26!을 상상했다면 그 어마어마한 규모에 놀랄수밖에 없다. 26!이 얼마나 큰지 생각해 보고 싶다면, 일단 1부터 26까지 사이에 있는 정수에는 10과 같거나 보다 큰 정수가 17개나 있다. 10을 17번만 곱해도 10경이다.

    스털링의 공식을 사용하면 대략의 크기를 추측해 볼 수 있는데, 아니면 그냥 구글에 검색하면 된다.

    26! = 4 x 10^26

    4뒤에 0을 26개 정도 붙여야 얼추 비슷한 값이 나온다는 뜻이다.

    일단 그정도의 경우의 수가 있는데, 이걸 저장하기 위해 필요한 하드디스크 용량은 얼마나 될까? 26글자로 이루어진 문자열이므로 대략 10을 28번정도 곱한 크기의 글자를 저장해야 하는데, 영어 1글자가 1바이트이므로 10^28바이트의 용량이 필요하다.

    1 GB = 10^9 Byte

    1 TB = 10^12 Byte

    1 PB = 10^15 Byte

    1 EB = 10^18 Byte

    1 ZB = 10^21 Byte

    1 YB = 10^24 Byte

    대략 1만 욕토바이트 정도.

    요새 1 TB하드디스크가 10만원 안쪽으로 살 수 있는데, 대량구매로 1 TB에 만원이라 치고, 그렇다고 쳐도 저장공간을 확보하기 위해서 필요한 예산은 1 해 원이다. 우리나라 한해 예산을 1천조원이라고 가정해도 그보다 10만배 더 큰 예산이다.

    저정도의 용량을 채우려면 1페타플롭스 정도 되는 컴퓨터를 사용해도 백만년 정도 출력해야 가능하다.

    자, 그건 그렇다 치고.

    A부터 Z까지 알파벳으로 이루어진 모든 경우의 수를 출력하려면 이론적으로는 어떻게 하면 될까?

    몇가지 알고리즘을 생각해 볼 수 있다.

    일단 밑바닥부터 생각한다면,

    A를 생각하고 여기에 B를 추가하면 AB와 BA가 있다. 그 두가지 경우에 대해 C를 추가하여 AB로부터 CAB, ACB, ABC를 만들고, BA로부터는 CBA, BCA, BAC를 만들어 낸다. 그렇게 만들어진 여섯가지 경우에 대해 D를 추가하고. 등등. 이런식으로 중간에 하나씩 끼워넣는 방법을 이용하여 만들어낼 수 있다.

    두번째로, 순수하게 정말 permutation의 의미를 생각해서 만드는 방법인데, ABCD…XYZ까지 다 써놓고, 1번과 2번을 바꾼 것, 1번과 3번을 바꾼 것, … 이렇게 해서 1번 바꿔서 만든 모든 문자열을 추가하고, 1번과 2번을 바꾸고 1번과 3번을 바꾸고, … 이렇게 해서 2번 바꿔서 만든 모든 문자열을 추가하고, …

    이렇게 해서 모든 경우의 수를 출력시킬 수 있다.

    세번째로, 대충 만들어도 된다고 하면 아무거나 ABCD…XYZ까지 다 써놓고, 26개의 난수를 생성하면서 그 위치에 있는 문자를 뽑아서 만들면 된다. 필요한만큼 만들고, 같은거 나오면 버리면 된다. 물론 난수가 제대로 생성되었다면 4*10^26개의 경우의 수 중에 겹치는 것이 나올 가능성은 거의 없다.

    이렇게 세가지 정도의 알고리즘을 생각해 볼 수 있다. 물론 이 알고리즘들은 널리 알려져 있는 방법들이다. 실제로 구현된 코드는 구글에서 permutation과 원하는 프로그래밍 언어 이름으로 검색하면 매우 많이 나오기 때문에 생략한다.

  • 문제가 나타났다

    잘 정의된 어떤 함수가 있다. 이걸 2차원에서 2중적분을 해야 하는데, 기왕에 하는거 제대로 개발된 라이브러리를 써보려고 GSL을 쓰려고 봤더니 생각해보니 GSL은 C에서 쓰는 것이더라.

    일단 만들어놓은 프로그램은 파이썬이기 때문에 GSL의 파이썬 포트인 pyGSL을 찾았는데, 윈도우용으로 컴파일된 바이너리는 윈32의 파이썬 2.5용. 나는 윈8 64비트 버전을 사용하므로 이걸 사용할 수 없다.

    1. 비주얼 스튜디오를 설치해서 GSL 바이너리를 윈8 64비트용으로 새로 컴파일하고 pyGSL도 다시 컴파일한다.

    2. C를 이용해서 새로 짠다. 이 경우 VS를 쓰든 gcc를 쓰든 쓰겠지.

    3. 윈도우를 32비트 버전으로 설치한다. 아…안돼.

    4. 2중적분을 그냥 내가 구현한다.

    여러가지로 고민하다가 일단 4번으로 진행해야겠다는 생각이 들었다. 1번은 너무 삽질인 것 같고 2번은 나중을 위해서 언젠가 하게 될 것 같은 작업이다. 2번으로 진행할 때는 MPI를 고려해야지. 알려진 함수의 적분이니까.