본문 바로가기
  • Top Genius in the world
알고리듬

[알고리듬] #64 가족 구성

by Mr.Algo 2024. 4. 20.
728x90
반응형

파이썬 실습창을 열 수 있습니다.실습창 열기

가정에서 마음이 평화로우면

어느 마을에 가서도 축제처럼 즐거운 일들을 발견한다.

-인도속담-

 

 

가족 구성

나이가 같은 부부가 터울이 같은 9명의 자녀를 두었습니다.

올해는, 자녀들의 나이를 각각 제곱하여 모두 더하면 부부의 나이를 곱한 것과 같습니다.

가족들의 나이는 얼마일까요?

 

인간이 150살까지 살 수 있다면 3가지 경우가 있습니다.

부부의 나이와 자녀의 나이입니다.
48 : 2 5 8 11 14 17 20 23 26
96 : 4 10 16 22 28 34 40 46 52
144 : 6 15 24 33 42 51 60 69 78

 

위와 같은 결과가 나오도로 프로그램을 작성하여 보세요.

부부(夫婦): 남편과 아내.
터울 : 한 어머니의 먼저 난 아이와 다음 난 아이와의 나이 차.
자녀(子女): 아들과 딸.
제곱 : 어떤 수를 그 수만큼 곱하는 것.

 

 

1, 문제 분석

문제의 핵심을 정리하여 봅시다.

  • 부부의 나이는 같다.
  • 터울이 같은 9명의 자녀가 있다.
  • 자녀들의 나이를 각각 제곱하여 모두 더하면 부부의 나이를 곱한 것과 같다.
  • 인간은 최대 150살까지 산다고 가정한다.
  • 부부의 나이와 자녀들의 나이를 구하자.

그런데 궁금한 것이 생겼습니다.

막내의 나이가 0살인 경우도 있을까?

터울이 0인 경우(쌍둥이들)도 있을까?

이러한 경우를 고려할 수도 있겠지만 막내는 1살부터, 9쌍둥이는 없다고 생각합시다.

 

 

2. 알고리듬 설계

개략적인 논리 구조는 막내의 나이를 1살 부터 증가시키면서 그때마다 터울을 1살부터 적용하여 보는 것입니다.

즉, 모든 경우를 조사하는 방법(brute force)을 생각할 수 있습니다.

막내 1살: 터울 1부터 150까지 조사
막내 2살: 터울 1부터 150까지 조사
:
:
막내 150살: 터울 1부터 150까지 조사

 

이러한 모든 경우에서 조건에 맞는 경우를 찾아내면 될 것 같습니다.

그런데,

부부의 나이가 같으므로 곱하면 제곱이 됩니다.

그러므로 아이들 나이를 제곱하여 더한 값이 제곱수인 것을 판단하여야 합니다.

제곱수는 어떤 수를 제곱한 수인데 4(2의 제곱), 9(3의 제곱), 16, 25 등이 제곱수입니다.

 

제곱수 판단은 0.5제곱하여 소수점 이하가 없으면 제곱수, 있으면 제곱수가 아닙니다.

예를 들어, 

4**0.5=2.0 이고, 5**(0.5)=2.236... 입니다.

그러므로 4는 제곱수이고, 5는 제곱수가 아닙니다.

 

3. 코딩하기

단계적으로 코딩하여 봅시다.

 

3-1 아이들 나이의 모든 경우 만들기

아이들 나이의 모든 경우가 발생되는 코드입니다.

eps=150                            # 나이 한계
kids=9                             # 아이들 수
for last in range(1,eps+1):        # 막내 나이
    for gap in range(1,eps+1):     # 터울 
        for i in range(kids):      
            age=last+gap*i         # 각 아이들의 나이
            print(age, end=' ')
        print()

'''
아이들 나이의 모든 경우가 출력됩니다.

1 2 3 4 5 6 7 8 9 
1 3 5 7 9 11 13 15 17 
:
:
150 299 448 597 746 895 1044 1193 1342 
150 300 450 600 750 900 1050 1200 1350 
'''

 

3-2  한계값 내의 나이만 출력

나이가 한계값(150살) 보다 많은 경우는 발생되지 않도록 할 수는 없을까?

막내의 나이와 터울을 알면 맏이(첫째 아이)의 나이를 알 수 있습니다.

        (맏이 나이) = (막내 나이)+ (터울) *8

그러므로 맏이 나이가 한계값 이내일때만 출력하면 됩니다.

eps=150                           
kids=9                            
for last in range(1,eps+1):         
    for gap in range(1,eps+1):      
        first=last+gap*(kids-1)      # 맏이의 나이  <---- 이곳부터 아래 수정
        if first<=eps:               # 맏이가 한계값 이내이면
            for age in range(last,first+1,gap):  
                print(age, end=' ')
            print()
            
'''
1 2 3 4 5 6 7 8 9 
1 3 5 7 9 11 13 15 17 
:
:
141 142 143 144 145 146 147 148 149 
142 143 144 145 146 147 148 149 150 

경우의 수가 많이 줄었습니다.
'''

 

 

3-3 조건에 맞는 경우 찾기

아이들 나이의 제곱합이 제곱수가 되는 경우를 찾아봅시다.

eps=150                           
kids=9                             
for last in range(1,eps+1):         
    for gap in range(1,eps+1):      
        first=last+gap*(kids-1)
        if first<=eps:
            s=0                        # 아이들 나이의 제곱을 모을 준비
            for age in range(last,first+1,gap):
                s+=age*age             # 제곱을 모음
            p=s**0.5                   # 0.5 제곱(루트 값을 구함)
            if p==int(p) and p<=eps:   # 제곱수이고 한계값 이하이면
                print(int(p))
                
'''
결과는 다음과 같습니다.
48
96
144
'''

 

3-4 완전한 출력

문제에서는 부모의 나이뿐만아니라 아이들의 나이도  출력하여야 합니다.

eps=150                                      
kids=9                             
for last in range(1,eps+1):         
    for gap in range(1,eps+1):      
        first=last+gap*(kids-1)
        if first<=eps:
            ages=[]                               # 나이를 모을 준비 <--- 이곳 추가                           
            s=0
            for age in range(last,first+1,gap):
                ages.append(age)                  # 나이를 모음 <--- 이곳 추가    
                s+=age*age
            p=s**0.5    
            if p==int(p) and p<=eps:
                print(int(p),':',*ages)           # 나이 출력   <--- 이곳 수정
                
'''
결과입니다.
48 : 2 5 8 11 14 17 20 23 26
96 : 4 10 16 22 28 34 40 46 52
144 : 6 15 24 33 42 51 60 69 78

*ages의 star(*)는 리스트의 압축해제입니다.
압축해제가 되지 않으면 14번 줄 대신에 다음과 같이 코딩하세요.
                print(int(p),':',end='')
                for i in ages:
                    print(i,end=' ')
                print()  

'''

 

3-5 간결한 문제

입사, 입학, 자격, 대회 등에서는 일반적으로 문제를 간결하게 출제합니다.

나이가 같은 부부가 터울이 같은 9명의 자녀를 두었습니다.
올해는, 자녀들의 나이를 각각 제곱하여 모두 더하면 부부의 나이를 곱한 것과 같습니다.
부부의 나이는 얼마일까요?
부부의 나이는 60을 넘지 않았습니다.

 

이러한 경우에는 다음과 같이 코딩할 수 있습니다.

eps=60      # 이곳 수정. 부모 나이가 60을 넘지 않음                                 
kids=9                             
for last in range(1,eps+1):         
    for gap in range(1,eps+1):      
        first=last+gap*(kids-1)
        if first<=eps:
            a=map(lambda x:x*x,range(last,first+1,gap))
            p=sum(a)**0.5    
            if p==int(p) and p<=eps:
                print(int(p))
 
 '''
 답은 48입니다.
 
 7번 줄의 람다(lambda) 함수는 다음에 공부합니다.
 이 문제에서는 for문 보다 간단합니다.
 '''

 

코딩의 세계는 끝이 없습니다.

인류 지혜의 보고(보물 창고)입니다.

 

끝까지 가 봅시다.

수고하셨습니다.

안녕!

728x90
반응형