How to Solve Problems

What is the first thing we should do to solve a problem like this one?(문제를 풀기위해 가장 우선되는게 무엇인가?)

  • Make sure we under stand the problem. (일단 뭐가 문제인지 아는게 중요하다.)
  • Search Google for the answer (연습할때가 아니라면 구글링을 해보는것도 좋다)

Understanding a (Computational) Problem(컴퓨팅적 문제 이하하기 - 뭐가문제이며 어떻게 풀지)

Given you birthday and the current date, calculate your age in days.
                └──inputs                      └──outputs

Problem is defined by Possible inputs(어떤값이 들어가는지 확실하게 알아라) relationship between inputs --> ouputs(desired)

Solution : input => <procedure> => output

  1. What are the inputs? "Given your birthday and the current date, calculate your age in days."
    1. birthday, current day
    2. second date must not be beofre first date => Defensive Programming (check this in our code)
  2. How are inputs represented? def days BetweeonDates(year1, month1, day1, years2, month2, day2)
  3. What are the ouputs? "... , calculate your age in days"
    1. return days between two input days
  4. Solve the problem!

Quiz : The Expected Output(to understand the relationship between the two inputs)

For each, give the expected output or undefined if there is no defined output.

daysBetweenDates(2012,12,7,2012,12,7) # => 0
daysBetweenDates(2012,12,7,2012,12,8) # => 1
daysBetweenDates(2012,12,8,2012,12,7) # => undefined
daysBetweenDates(2012,6,29,2013,6,29) # => 365
daysBetweenDates(2012,6,29,2013,6,31) # => undefined

Before solving the problem

  • understand the inputs
  • understand the ouputs
  • understande the relationship - some examples
  • Consider systematically how a human solves the problem

Algorithm "pseudo code"

Example : counting the number of days remaining1 in january

days = number of days in month1 - day1 # 31 - 24 = 7
month1 += 1 # 2월로 넘어간다

while month1 < month2:
    days += number of days in month1
    month1 += 1

days += days2

while year1 < year2:
    days += days in year1

doesn't handle:

  • input dates in smae month
  • month2 < month1, years2 > years1

It's too complex we should try to find a simpler ways


Simple mechanical algorithm

days = 0
while date1 is before date2:
    date1 = advance to next days # => nextDay
    days += 1
return days

nextDay(year,month,day)

Define a simple nextDay procedure, that assumes every month has 30 days.

### nexDay(2017,3,1) => 2017,3,2
### nexDay(2017,3,30) => 2017,4,1

#민우코드
def nextDay(year, month, day):
    """Warning: this version incorrectly assumes all month have 30 days!"""    
    if day < 30:
        day += 1
    else:
        day = 1
        if month < 12:
            month += 1
        else:
            month = 1
            year += 1

    return year, month, day

#udacity
def nextDay(year, month, day):

    if day < 30:
        return year, month, day + 1
    else:
        if month < 12:
            return year, month+1, 1
        else:
            return year + , 1, 1

# 내코드가 더 이해하기 쉬운걸?

dayBetweenDates

Define an (approximate2) daysBetweenDates procedure that would produce the correct results given a correct nextDay procedure

#민우코드
def daysBetweenDates(year1, month1, day1, year2, month2, day2):
    days = 0
    year,month,day = year1,month1,day1

    while True:
        if (year == year2) and (month == month2) and (day == day2): break
        else:    
            year,month,day = nextDay(year,month,day)
            days += 1

    return days

#되게 기특한걸?
#year,month,day 변수를 만들 필요는 없지만, 난 원래 따로 저장해두는게 좋다.
#udacity
#helpercode 나는 이부분을 if/else로 이용하고 루프를 돌렸다.

def dateIsBefore(year1, month1, day1, year2, month2, day2):
    """Returns True if year1, month1, day1 are before year2, month2, day2"""
    if year1 < year2: #년도가 작다면 더이상 볼필요가 없다.
        return True
    if year1 == year2:
        if month1 < month2: #년도가 같으면 월이라도 작아야한다.
            return True
        if month1 == month2:
            return day1 < day2 #년과 월이같으면 일이라도 작아야한다.

    return False #다 아니면 이거 작은게 아니다. (같거나 크다)

def daysBetweenDates(year1, month1, day1, year2, month2, day2):
    days = 0
    year,month,day = year1,month1,day1

    while dateIsBefore(year1, month1, day1, year2, month2, day2):
        year1,month1,day1 = nextDay(year,month,day)
        days += 1

    return days

#helpercode를 사용하면 아무래도 좀더 정확할것 같다. 내코드는 어느 날짜가 빠른지 확인이 안된다. 그냥 믿고 대입..
# => 앞에 대입하는 날짜가 큰경우에 0을 반환한다. 이건 문제다.
# 내코드 if/else 문에 else if로 이걸 넣는게 솔루션이 되지 않을까?
#udacity는 새로운 변수를 만들지 않았다. 이부분은 내코드가 더 좋다고 생각한다.
#왜냐면 새로운 변수를 만들어 사용하고 이전값을 보전하는게 유지보수하기 좋다고 생각하기 때문이다.

Add an assertion3 to daysBetweenDates to give an assertion failure when the inputs are invalid4

#민우코드
def daysBetweenDates(year1, month1, day1, year2, month2, day2):
    """Returns the number of days between year1/month1/day1
       and year2/month2/day2. Assumes inputs are valid dates
       in Gregorian calendar."""
    # program defensively! Add an assertion if the input is not valid!

    days = 0
    year,month,day = year1,month1,day1

    while True:
        if dateIsBefore(year, month, day, year2, month2, day2):
            year, month, day = nextDay(year, month, day)
            days += 1
        elif (year == year2) and (month == month2) and (day == day2): 
            return days
        else:
            assert not dateIsBefore(year2, month2, day2, year, month, day)


# 원래 내코드에 dateIsBefore()을 넣었다.
# 근데 이건 한번만 확인하면 되는건데 매번 확인하는것 같아서 별로다.
#udacity
def daysBetweenDates(year1, month1, day1, year2, month2, day2):

    # program defensively! Add an assertion if the input is not valid!
    assert not dateIsBefore(year2, month2, day2, year1, month1, day1)
    days = 0

    while dateIsBefore(year1, month1, day1, year2, month2, day2):
        year1, month1, day1 = nextDay(year1, month1, day1)
        days += 1    
    return days

# assert를 이렇게 쓰는거구나! 레일즈의 before_action 같은느낌!
# assert 뒤에 true가 나오면 작동하는건가? 근데 여전히 같은 날에 대한 대응은 안되는것 같은데?
# => 대응 된다. 날짜가 같은경우에는 에러를 안밷는것 같은데 왜지? . 내코드에서 elif와 else를 합친게 저한줄..ㅠ

Finish daysBetweenDates

추가할 프로시저(procedure: 함수)

  • daysInMonth(year, month)
  • isLeapYear(year)
#민우코드
def isLeapYear(year):
    if year%400 ==0:
        return True
    elif year%100 == 0:
        return False
    elif year%4 ==0:
        return True    
    else:
        return False

def daysInMonth(year,month):
    days = [31,28,31,30,31,30,31,31,30,31,30,31]
    if isLeapYear(year) and month==2:
        return 29
    else:
        return days[month-1]
#udacity
def daysInMonth(year,month):
    #1,3,5,7,8,10,12
    if month == 1 or month == 3 or month == 5 or month == 7 \
        or month == 8 or month == 10 or month == 12:
        return 31
    elif month == 2:
        if isLeapYear(year):
            return 29
        else:
            return 28
    else:
        return 30

# isLeapYear()은 내코드와 동일하다.
#내코드가 가독성이 좋은건 그냥 내꺼라서 그런가ㅋㅋㅋㅋㅋ
#유지보수용으로는 이 코드가 더 좋을것 같다.

nextDay에 추가

def nextDay(year, month, day):
    if day < daysInMonth(year,month):
        return year, month, day + 1
    else:
        if month == 12:
            return year + 1, 1, 1
        else:
            return year, month + 1, 1

Test Case 추가

def test(): 
    assert daysBetweenDates(2013, 1, 1, 2013, 1, 1) == 0
    assert daysBetweenDates(2012, 2, 28, 2012, 3, 1) == 2
    assert daysBetweenDates(2017, 5, 24, 2018, 7, 27) == 429
    assert nextDay(2013, 1, 1) == ( 2013, 1, 2)
    print "Test Finish"

test()

다시하니까 그렇게 많이 안어렵고 강의에서 잘알려준것 같다.

신난다~~~!

1. remain : 남아있다. 잔류하다.
2. approximate : 근접한
3. assertion : 주장을 표명, 단언
4. valid/invalid : 유효한 / 유효하지 않은(무효인)

results matching ""

    No results matching ""