기타 강좌

3두개 7두개로 24를 만들려면?을 스킴으로 풀기

3두개 7두개로 24를 만들려면?을 스킴으로 풀기
이번 강좌는 어느 카페에서 올라온 3두개 7두개로 24를 어떻게 만드나?하는 퀴즈에서 시작되었다.
사칙연산으로 3두개와 7두개로 24를 만들려면 어떻게 해야하나?
아마 대부분 머릿속에서 일일이 대입하고 있는 사람이 많을것이다.
원리를 꿰뚫어서 푼다면 당신은 천재 -_-;;;

나의경우는 스킴이라는 언어를 배우고 있을때여서 스킴으로 풀어볼까 했다.
그런데 방법을 몰라서 멍때리고 있다가 카페에서 순열을 구하는 코드를 득템해서 풀어보게 되었다. 물론 처음 하는거라서 실수도 있었지만 원하는 값을 찾을 수 있었다.

자 그럼 어떻게 만들지 구상을 해보자.
나의 경우는 
(+ (+ (+ (+ 3) (+ 7)) 3) 7)
부터
(/ (/ (/ (- 3) (- 7)) 3) 7)
까지
그냥 일일이 다 대입해서
파일에 한 줄 한 줄저장했다.
그중에 맞는게 있지 않겠는가? 후후..
그리고 그 데이터들을 읽어와서 실행해봤다.
엄청난 장점 중 하나로 스킴은 데이터와 코드의 구분이 없다! 물론 리습도 'ㅅ'
그래서 글자들을 읽어와서 그대로 실행할 수 있는 것이다.
(가령 (+ 1 2)를 파일에서 읽어와서 실행하면 3이 나온다.)
실행해서 24와 같으면 그 식을 출력하고 아니면 넘어간다.

후훗.. 실행해본 결과
(+ (+ (+ (+ 7) (+ 7)) 7) 3)
(+ (+ (+ (+ 7) (+ 7)) 7) 3)
(+ (+ (+ (+ 7) (+ 3)) 7) 7)
(+ (+ (+ (+ 7) (+ 3)) 7) 7)
(+ (+ (- (+ 7) (- 7)) 7) 3)
(+ (+ (- (+ 7) (- 7)) 7) 3)
(+ (+ (- (+ 7) (- 3)) 7) 7)
(+ (+ (- (+ 7) (- 3)) 7) 7)
(- (* (* (+ 3) (+ 3)) 3) 3)
(- (* (* (+ 3) (+ 3)) 3) 3)
(- (* (* (- 3) (- 3)) 3) 3)
(- (* (* (- 3) (- 3)) 3) 3)
(* (+ (/ (+ 3) (+ 7)) 3) 7)
(* (+ (/ (+ 3) (+ 7)) 3) 7)
(* (+ (/ (+ 7) (+ 7)) 7) 3)
(* (+ (/ (+ 7) (+ 7)) 7) 3)
(* (+ (/ (- 3) (- 7)) 3) 7)
(* (+ (/ (- 3) (- 7)) 3) 7)
(* (+ (/ (- 7) (- 7)) 7) 3)
(* (+ (/ (- 7) (- 7)) 7) 3)
이렇게 나왔다 
내 코드가 잘 못 되어서 이렇게 나온거다;;
우선 같은게 두개씩 출력되었고 
3두개 7두개가아니라 3 네개나 3 세개 + 7한개 같은거도나와버렸다. 
아무래도 숫자 넣는 칸에 3과7로 만들수 있는 모든 경우의 수를 계산해버린거같다.
그럼 뭐 어떤가? 답이 나왔는데...-_-;;
3두개 7두개인것을 추려보고 두개인것을 하나로 추려보면
(* (+ (/ (+ 3) (+ 7)) 3) 7)과 
(* (+ (/ (- 3) (- 7)) 3) 7)가 나온다!
자 그럼 계산기로 계산해보자 3나누기 7한것에 3을 더한뒤 7을 곱하면 24가 나온다 후훗...!
음수 3을 음수 7로 나누고 3더하고 7곱해도 역시나 24가 나온다. 

자 코드를 살펴보자

핵심 함수는 다음과 같다.
우선 눈에 익혀두자 아래에 설명할 것이다.

==모든 경우의 수===
for
for*/list
=================================

===데이터 변환===
list->string 
=================

===파일에 출력(기록)(파일을 열어야 기록할 수 있다.)===
open-output-file
display
===================

===파일에서 읽어오기===
open-input-file
read
========================

===파일에서 읽어온 식을 실행===
make-base-namespace
eval
===============================

자 이제 설명을 해보겠다.

==모든 경우의 수===
===for===
변수 먼저 적고 그뒤에 몸체가 있다는 함수 선언 하는것과 비슷하다.
(for () ())
for뒤에 오는 첫번째 괄호에는 [변수 리스트]를 넣고 
팁>> []가 여러개 넣어도 된다.
팁>> []는 ()과같다. 그런데 계속 ()만 쓰면 눈아프니까 'ㅅ';;
두번째 괄호에는 그 변수들을 가지고 연산을 하는 칸이다. 
비워두면 오류나므로 뭔가 적어두자.
(for ([i '(1 2 3)]
      [j "abc"]
      [k '(j k l)])
  (display (list i j k)))
for는 리스트중에 
팁>> "abc"는 '(#a #b #c)와 같다고보면 된다. #는 뒤에 문자가 온다는 뜻.
팁>> #space는 공백을 뜻한다.
for가 첫번째 돌때는 각각 리스트의 첫번째 원소 값이 각각 변수 i j k에 저장되고 
두번째 돌때는 두번째 세번째돌때는 세번째 원소값이 변수에 저장된다.
(1 a j)(2 b k)(3 c l)가 나온다.
그럼 다음과 같은 코드는 어떻게 출력될까?
(for ([i '(2 3 4 5 6 7 8 9)])
  (printf "2 * ~a = ~an" i (* 2 i)))
다음과 같이 출력된다.
2 * 2 = 4
2 * 3 = 6
2 * 4 = 8
2 * 5 = 10
2 * 6 = 12
2 * 7 = 14
2 * 8 = 16
2 * 9 = 18
========= 

===for*/list===
(for*/list ([변수1 리스트1] [변수2 리스트2] [변수3 리스트3])
  (변수사용하는 함수))
이 함수 역시 for와 마찬가지로 for*/list뒤에 첫째 괄호안에 [변수 리스트]를 여러개 적고 
(리스트를 하나만 적으면 for나 for*/list나 차이가 없다. 여기서는 3개를 적었다.)
그뒤의 괄호안에는 그 변수를 사용하는 계산이 온다.
(for*/list ([i '(1 2 3)]
            [j "abc"]
            [k '(j k l)])
  (list i j k))
그럼 이 코드의 결과는 어떻게 나올까?
한마디로 말하자면 모든 경우의 수가 리스트로 나온다.
다음은 위에 적어둔 for*/list의 결과이다
'((1 #a j) >>첫번째 돌아서 (list i j k)를 실행시킨 결과.
  (1 #a k)
  (1 #a l)
  (1 #b j)
  (1 #b k)
  (1 #b l)
  (1 #c j)
  (1 #c k)
  (1 #c l)
  (2 #a j)
  (2 #a k)
  (2 #a l)
  (2 #b j)
  (2 #b k)
  (2 #b l)
  (2 #c j)
  (2 #c k)
  (2 #c l)
  (3 #a j)
  (3 #a k)
  (3 #a l)
  (3 #b j)
  (3 #b k)
  (3 #b l)
  (3 #c j)
  (3 #c k)
  (3 #c l))

===for*===
for*라는 함수도있는데 for*와 for*/list의 차이점은 for*/list는 결과들을 리스트로 묶는다는 것이다. for*/list의 결과를 보면 가장 가장자리에 '()가 있는 것을 볼수있다.
for*를 연습해보고 싶다면
다음과 같이 해보라. display를 추가했다.
(for* ([i '(1 2 3)]
       [j "abc"]
       [k '(j k l)])
  (display (list i j k)))
==========

==여기서 잠깐.연습문제!===
for*/list를 사용해서 구구단을 출력해 보아라.
힌트>>#lang scheme 포함하고 들여쓰기 해서 4줄이면 된다.
==========================
===============
====================
무언가 감이 오지 않는가?
for*/list를 사용해서 모든 경우의 식들을 만들고
for를 사용해서 그 식들하나하나를 문자열로 바꿔서 저장하게 될것이다.
저장 용량은 뭐 200KB안에서 해결되더라.

===데이터 변환===
===list->string===
'(1 2 3)같은 리스트를 "1 2 3"과 같은 문자열로 바꿔준다.
파일에 리스트가 아닌 문자열을 출력하기 때문에 사용한것임.
(list->string (list 변수1 변수2 변수3 등등))는 
변수1 변수2 변수3 등등을 리스트로 만들고 그 리스트를 문자열로 바꾼다.
여기서는 변수자리에 #( 같은게 들어갔는데 #는 뒤에 따라오는 문자 하나를 뜻한다.
#)는 닫은 괄호를 뜻하고 #a은 문자 a를 뜻한다.
즉 "(+ (+ (+ (+ 3) (+ 3)) 3) 3)" 이런걸 만드라는 의미이다.
팁>> '(1 (+ 1 1) 3)은 문자 그대로 '(1 (+ 1 1) 3)인 리스트이다.
     하지만 (list 1 (+ 1 1) 3)은 '(1 2 3)이 된다. 
     즉 안의 계산을 먼저하고 그걸 리스트로 만드는 것이다.
=================

===입력과 출력이 헛갈리는 분들을 위한 팁===
input은 입력 output은 출력이다. 
입력은 파일에서 받을수도 사용자에게 받을수도 있다.
출력은 화면에 출력할수도있고 파일에 출력할수도 있다.
입력이라고 해서 파일에다가 입력하라는 뜻이 아니다.
입력은 받는거 출력은 뿌리는 것이다.
===========================================

===파일에 출력(기록)(파일을 열어야 기록할 수 있다.)===
팁>> 출력이라는 말이 헛갈릴수 있는데 파일에 출력이라함은 파일에 기록하는것이다.
팁>> 경로를 따로 지정안하고 
     이름만 적어두었으니 소스가 저장된 곳에 test.txt가 생길것이다.
     (소스를 저장 안 했으면 Racket설치 폴더에 test.txt가 생길것임.)
(define out (open-output-file "test.txt"))
=> 파일열고 out에 대입한다.
=> 이제 out에다가 출력하면 test.txt에 글자가 써진다.
(display strings out)
=> strings안에 든 내용을 out(즉 test.txt)에 출력한다.
(display "rn" out)
=> r은 커서를 가장 앞으로 옮기고 n은 다음줄로 넘어간다는 뜻이다. 
=> n만 쓰면 메모장으로 열때 깨진 문자를 볼수 있을것이다.
팁>> 이렇게 string따로 rn따로 나누어서 파일에 출력 하고싶지 않다면 
     (fprintf o "~arn" strings)처럼 쓴 후에 
     o문자열을 한번에 파일에 출력하는 방법이 있다.
     o에 출력하기 전에 (define o (open-output-string))이런 코드를 적어둬야 된다.
열었던 파일을 (close-output-port out)로 닫아주는 센스!!
================================================

===파일에서 읽어오기===
(define in (open-input-file "test.txt"))
=> 파일을 열고 in에 대입했다. 
=> 이제 in을 읽어서 출력하면 파일에서 한줄씩 읽어와서 출력된다.
(display (read in))
=> read로 in을 읽어서 출력했다.
팁>> display를 위에서는 파일에 출력할때 썼는데 
     뒤에 아무것도 안 적어주면 화면에 출력하라는 뜻이다.
=> 파일을 열어야 파일에서 읽어올 수 있다.
주의>> (open-input-file "test.txt")을 실행하면 파일의 처음부터 읽기시작한다.
       만약 (read (open-input-file "test.txt"))을 
       10번실행하면 10번 모두 첫줄만 나올것이다.
       하지만 (read in)으로 적고 10번 실행하면 한줄씩 넘어가서 10줄이 나올것이다.
       즉 읽을때 가르키는 곳이 한번 읽을때마다 다음 줄로 넘어간다.
=======================

===파일에서 읽어온 식을 실행===
(이 namespace와 eval 부분은 필자도 자세히 모르므로 틀려도 양해 바란다 'ㅅ';;)
===make-base-namespace===
namespace는 기호들과 기호와 관련된 정보를 연결해 놓은 자료이다.
eval로 불러온 식을 실행할때 기호들이 무슨 역할을 하는지 여기서 참조한다.
그냥 간단하게 eval 쓰기 전에 
(define ns (make-base-namespace)) 이런식으로 선언해준다고 생각하자.
=========================
===eval===
eval은 evaluation의 약자다. 평가라는 뜻이다.(수학에서 값을 구한다라는 뜻이다.)
필자는 실행이라는 단어를 많이 썼는데 사실 평가라는 단어가 정석이다.
eval은 뒤에 오는 리스트 데이터를 코드라고 생각하고 실행한다.
실행할때 기호들을 어떻게 실행할지는 마지막에 오는 namespace 를 참조한다.
'(+ 1 2 3)이 있다면 +가 기호/함수 이다. 
(eval '(+ 1 2 3) ns) 이렇게 적고 실행하면 6이 나올것이다.
여기에서는'(+ 1 2 3)대신에 위에서 for*/list로 만든 식이 들어올것이다.
다음과 같이 적을것이다.
(eval found ns)
found에는 다음과 같은 값이 들어갈것이다. 
주의>> ??는 생략했다는 뜻. ??를 적는다는의미가 아니다 -_-;;
(let ((found (read in))) (??))
found에다가 in 파일에서 read한 식을 한줄씩을 저장하므로 
'(+ (+ (+ (+ 3) (+ 7)) 3) 3) 이런 데이터가 저장 될것이다.
스킴은 데이터와 코드의 구분이 없으므로 이걸 실행할수 있다!!
왜 found에다가 저장한 다음에 
24인지 비교해서 맞으면 found를 출력했냐는 사람들이 있을것이다.
그건 (= (eval (read in) ns) 24)와 같이하면 24일때 그 식을 출력하기 어렵기 때문이다.
(필자가 모르는 것일수도 -_-;;)
==========
===============================

다음 편에 계속된다.

Who's 정체불명

profile

두팔과 의지가 있는데 무엇을 못 하겠는가!

< http://mpnp.tistory.com >


List of Articles
분류 제목 글쓴이 날짜 조회 수
Vegas Pro 베가스 강좌 목록 아방스 2017.09.28 886
파이널컷X 파컷 강좌 목록 아방스 2017.06.18 757
기타 해커스쿨 F.T.Z서버에 대해 궁금하신 분들은 글올려주세요... - 하늘 - 2009.08.03 3428
C언어 한글자씩 출력하기 file 정체불명 2012.01.21 3729
플래시 플래시 MX 활용법! 1 은색바람 2011.09.09 2796
어도비 프리미어 프리미어 cc 2014 새로운 기능 - Premiere Pro CC – April 2014 – New Features 아방스 2014.07.07 1443
게임기획 프롤로그의 여러가지 작성 방법 2 아방스 2012.04.17 4135
기타 프로그래밍 스킴 Scheme 4 "3두개 7두개로 24를 만들려면?" 프로그래밍으로 풀기 2 정체불명 2010.10.03 2479
기타 프로그래밍 스킴 Scheme 3 "3두개 7두개로 24를 만들려면?" 프로그래밍으로 풀기 1 정체불명 2010.10.03 2606
기타 프로그래밍 스킴 Scheme 2 프로그래밍한 걸 exe파일 만들어 배포하기! 2 file 정체불명 2010.10.02 3156
기타 프로그래밍 스킴 Scheme 1 다운로드부터 문법 대부분을 314초만에 알려줄게요 9 file 정체불명 2010.10.02 4828
기타 프로그래밍 스킴 7줄로 윈도우창에 그림을 출력하고 움직여보자. file 정체불명 2010.10.04 2477
기타 프로그래밍 scheme 빨간 공을 움직이다가 특정 좌표에 가면 파랗게 만들어 보자. file 정체불명 2010.10.06 2648
C언어 푸쉬푸쉬 func.h파일 file 정체불명 2012.01.25 2868
C언어 푸쉬푸쉬 data structure.h 의 내용 file 정체불명 2012.01.25 2596
기타 폴더 100개 일괄적으로 만들기 정체불명 2014.11.02 739
기타 포토스케이프 - 사진 색감 보정하기 아방스 2010.11.04 2782
기타 포토샵 크기 조절 1 제니스 2008.06.22 3914
기타 포샵 빛나는 공 4 제니스 2008.06.22 3075
에프터 이펙트 펜툴을 이용해서 키프레임 추가,삭제 및 수정방법 아방스 2011.12.08 5204
C언어 파일읽어서 배열에 넣고 다시배열에서 읽어서 화면에 출력 정체불명 2012.01.21 2701
기타 파이썬 총 강좌파일 올립니다... 3 file - 하늘 - 2009.09.10 7007
Board Pagination Prev 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 Next
/ 19