잔돈 바꾸기를 더 효율적으로 짜는 방법이 뭐가 있을까요?

notexist의 이미지

SICP책을 보다가 잘 모르겠어서...다른 분들의 좋은 아이디어를 알고싶어서 글을 올립니다.

(define (count-change amount)
    (cc amount 5))

(define (cc amount kinds-of-coins)
    (cond ((= amount 0) 1)
              ((or (< amount 0) (= kinds-of-coins) 0)) 0)
              (cc (- amount 
                        (first-denomination kinds-of-coins))
                    kinds-of-coins)))))

(define (first-denomination kinds-of-coins)
    (cond ((= kinds-of-coins 1) 1)
              ((= kinds-of-coins 2) 5)
              ((= kinds-of-coins 3) 10)
              ((= kinds-of-coins 4) 25)
              ((= kinds-of-coins 5) 50)))

책에 있는 코드는 위와 같습니다.

그리고 다음과 같은 말이 있습니다.

Quote:
On the other hand, it is not obvious how to design a better algorithm for computing the result, and we leave this problem as a challenge.

머리가 나쁜건지 노력부족인지 좋은 생각이 나지를 않습니다.
좋은 길을 가르쳐주셨으면 합니다.

P.S:옮겨치다가 괄호가 몇 개 틀린게 있어서 고쳤습니다.
또 틀린게 있을지 모르겠는데...뭐 내용 보는데 문제는 없겠죠?

cinsk의 이미지

흠.. SICP는 안 읽어봐서 잘 모르겠지만, Scheme 언어로 만든 예제 같은데, 이거 좀 잘못된 소스 같은데여. 제대로 짠 거 맞나여?

괄호가 엉망으로 되어 있는 것 같은데... ^^;

그리고 잔돈 바꾸기가 구체적으로 뭔지도 써 주시면 답변하기가 더 쉽겠죠? :)

mach의 이미지

12년전에 보았던 Lisp언어와도 비슷해보이긴 합니다만.
:oops:

------------------ P.S. --------------
지식은 오픈해서 검증받아야 산지식이된다고 동네 아저씨가 그러더라.

hurryon의 이미지

으흠...글쎄요...기억을 더듬어 보면 탐욕적 알고리즘으로 해결하는 문제
아닌가요?

아닌가?

배냥 채우기...뭐 이런거랑 같이 공부했던 기억이...

ㅡ.ㅡ;;

notexist의 이미지

말이 애매하네요...쓰고보니...

주어진 돈을 주어진 동전로 바꾸는 방법이 몇 가지인지 구하는 문제입니다.

예를 들어 돈이 100원인데...

동전이 50원, 10원 이렇게 2가지 종류가 있다면...

50:2개
50:1개, 10:5개
10:10개

이렇게 3가지 방법이 있겠죠?

위의 예에서는

(count-change 100)하면 292가 나옵니다.

P.S:Lisp이랑 비슷해보이는게 scheme은 lisp방언입니다...ㅡㅡa

There is more than one way to do it...

kn31232의 이미지

제 기억이 맞다면 Greedy Algoritm에서 보았던 Knapsack Algoritm을 말씀하시는거 같은데....

전 그냥 간단하게 해결했었는데....^^;

뭐 무식한 방법이라면야 동전의 액수를 순차정렬하여 한번씩 빼주면서 카운트 올려주는 루프를 돌려주는방법도 있을테고...

저같은 경우는 나머지 연산자를 써서 했었는데...

액수를 나눠서 몫은 카운트로 나머지 연산 결과는 적은 액수의 동전으로 다시 나머지 연산하고...또 몫은 카운트...나머지는 또 다시 적은 액수....

이렇게 하면 자릿수만큼만 루프를 돌려주면 되죠...

飛上

potatoid의 이미지

두번째 procedure가 이상한 것 같은데요.
cc 를 define하는 코드 말이죠.

다시 한번 더 오리지날 코드를 확인 해서 수정해주시면 로직을 완전히 이해할 수 있을 것 같아요.

그냥 대충 때려 잡기로는...

count-change는 동전의 종류를 5개로 잡았을 때 잔돈의 갯수를 카운트 해주는
cc 를 call 해주는 procedure 일뿐일 거구요.

세번째 first-denomination 는 첫번째 동전의 액면 금액을 return해주는 procedure이죠.
즉 동전의 종류가 1이면 1, 2이면 5 이런 식으로요..

아마 달러를 기준으로 환산한 것 같은데요..왜냐하면..
1: cent, 5 : nickel, 10 : dime, 25 : quarter, 50 : ?
이런 식으로 우리나라는 25원짜리 동전이 없죠..
근데 50 cents 짜리 동전도 있는 지 아직 본 적이 없는데.. 헤헤.

그리고 가장 중요한 두번째 procedure : cc
여기서 동전의 양을 줄여가면서 recursion을 돌리고 있는 데요.
일단 이 코드 데로는 제대로 된 recursion이 안 되고요.
recursion이 제대로 되도록 수정했을 때, 다시 한 번 더 보고 싶은데요.

아무튼 간단하게 제가 건져 본 내용입니다.

- ps-
일단 syntax error없이 위 코드를 수정했을 때 나온 결과는 님이 말씀하신
(count-chage 100) => 292 가 안되고 그냥 5가 되더라구요.

그럼.

--------------------------------------------------------------------------
Sorrow is better than laughter, because a sad face is good for the heart.

sozu의 이미지

Money System 문제 같은데...

아마 Greedy로는 Optimal Solution이 나오지 않을겁니다.

저는 Dynamic 으로 풀었었습니다.

ACMICPC에 나오는 문제거든요.

비슷한 문제가 어떤 아이가 N번째 계단을 오르는데 한번에 1계단, 2계단만

오를수 있다면, N번째 계단까지 오를수 있는 경우의 수를 구하는 문제입니다.

하지만 다른점은 계단문제에서는 순서가 있습니다.

1계단 -> 2계단 과
2계단 -> 1계단 이런식으로 순서가 존재하죠

하지만 Money System에서는

1원 + 2원
2원 + 1원은 같은 것이 되겠죠.

#include<stdio.h>

int coins[10] = { 5, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000};
int nways[5001];
float money;

main(){

        int i, j;

        nways[0] = 1;

        for(i = 0; i < 10; i++){
                for(j = coins[i]; j < 5001; j++) 
                         nways[j] += nways[j - coins[i]];
        }

        while(scanf("%f", &money) > 0 && money != 0){
                float tmp = money * 100;
                printf("%5.2f%12d\n", money, nways[(int)tmp]);
        }
        return 0;
}

이건 그때 풀었던 소스입니다.

-----------
청하가 제안하는 소프트웨어 엔지니어로써 재미있게 사는 법
http://sozu.tistory.com

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.