다음은 달력에 관한 몇 가지 일반적인 정보입니다 (필요한 경우 좀 더 연구를 해 보셔도 좋습니다).
20세기 (1900년 1월 1일 ~ 1999년 12월 31일) 에서, 매월 1일이 일요일인 경우는 총 몇 번입니까?
34개의 풀이가 있습니다.
날짜 관련한 라이브러리는 쓰지 말라는 제약은 없으므로 다음과 같이 풀었습니다.
참고로 20세기는 1901년부터 2000년까지입니다.
import datetime
s = 0
c = datetime.datetime(1901, 1, 1)
d = datetime.timedelta(days=1)
while c.year < 2001 :
if c.day == 1 and c.weekday() == 6:
s += 1
c += d
print(s)
days = ['Sunday', 'Monday', 'Tuesday', 'Wdnesday', 'Thursday', 'Friday', 'Saturday']
isleaf = lambda x: x % 400 == 0 or x % 100 != 0 and x % 4 == 0
day, cnt = 1, 0
for year in range(1900, 2000):
dom = [0, 31, 28+isleaf(year), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
for month in range(1, 13):
cnt += days[day] == 'Sunday'
day = (day + dom[month]) % 7
print(cnt) # 172
# python 3.6
import calendar
# sum(각 월의 첫 요일이 일요일(6)인 경우 1인 리스트 반환)
print(sum([1 if calendar.monthrange(x, y)[0] == 6 else 0 for x in range(1900, 2000)
for y in range(1, 13)]))
# ans: 172
Ruby
풀이 1 - stdlib 사용
require 'date'
(1900..1999).sum {|y| (1..12).count {|m| Date.new(y,m,1).sunday? } } #=> 172
풀이 2
def cnt_day1_sunday(from, to, week)
wday = %w(sun mon tue wed thu fri sat).index(week)
leap_day = ->year { year%4 == 0 && year%100 != 0 || year%400 == 0 ? 1 : 0 }
month = ->year { [3, 0+leap_day[year], 3, 2, 3, 2, 3, 3, 2, 3, 2, 3] }
(from..to).sum([], &month).count {|d| wday = (wday+d) % 7; wday == 0 }
end
Test
expect(cnt_day1_sunday(1900, 1999, "mon")).to eq 172
expect(cnt_day1_sunday(1901, 2000, "tue")).to eq 171
// golang 1.9
package main
import (
"fmt"
"time"
)
func main() {
stime := time.Date(1900, time.January, 1, 0, 0, 0, 0, time.UTC)
etime := time.Date(1999, time.December, 31, 0, 0, 0, 0, time.UTC)
// 1990.1.1->1999.12.31 1day 증가하며 매월 1일 && "Sunday"인 경우 카운트
count := 0
for !(stime == etime) {
if stime.Day() == 1 && stime.Weekday().String() == "Sunday" {
count++
}
stime = stime.AddDate(0, 0, 1)
}
fmt.Println(count)
}
// ans: 172
public class Calculate {
public static void main(String[] args) {
int dw = 0; //월화수목금토일 위치 - 0부터 시작
int [][] endDD = {{ 1, 31},{ 2, 28},{ 3, 31},{ 4, 30},{ 5, 31},{ 6, 30},{ 7, 31},{ 8, 31},{ 9, 30},{10, 31},{11, 30},{12, 31}};
int result = 0;
for( int y=1900 ; y<=1999 ; y++){
for(int m=1 ; m<=12 ; m++){
// 윤달 계산
if(m==2 && y%4==0){
endDD[1][1] = 29;
if(y%400!=0 && y%100==0)
endDD[1][1] = 28;
}
if(dw == 6) result +=1; //이번달 1일 요일 확인
dw = (dw + endDD[m-1][1]%7)%7; //다음달 1일 요일 위치로 이동
}
}
System.out.println(result);
}
}
count = 0
count2 = 0
for y in range(1900, 2000):
if y % 4 == 0:
for m in range(1, 13):
if m == 2:
for d in range (1, 30):
if d == 1 and count % 7 == 6:
count2 = count2 + 1
count = count + 1
elif m == 4 or m == 6 or m == 9 or m == 11:
for d in range (1, 31):
if d == 1 and count % 7 == 6:
count2 = count2 + 1
count = count + 1
else:
for d in range (1, 32):
if d == 1 and count % 7 == 6:
count2 = count2 + 1
count = count + 1
else:
for m in range(1, 13):
if m == 2:
for d in range (1, 29):
if d == 1 and count % 7 == 6:
count2 = count2 + 1
count = count + 1
elif m == 4 or m == 6 or m == 9 or m == 11:
for d in range (1, 31):
if d == 1 and count % 7 == 6:
count2 = count2 + 1
count = count + 1
else:
for d in range (1, 32):
if d == 1 and count % 7 == 6:
count2 = count2 + 1
count = count + 1
print (count2)
ms = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
day = -30
cnt = 0
for y in range(1900, 2000):
if not y % 400 or (not (y % 4)) and (y % 100):
ms[1] = 29
else:
ms[1] = 28
for m in range(1, 13):
day = (day + ms[m-1]) % 7
if not day:
cnt += 1
print(cnt)
python3 20세기(1900~1999)
풀이1
import datetime
print(str([datetime.date((i%100)+1900,i//100,1).weekday() for i in range(100,1300)]).count("6"))
풀이2
import calendar
print(str([calendar.monthrange(i%100+1900,i//100)[0] for i in range(100,1300)]).count("6"))
START_YYYYMMDD = 19000101 END_YYYYMMDD = 19991231
조건문을 쓰지 않기 위해 데이터의 구조를 변경해야 합니다.
DAY는 1일로 고정이기 때문에 DAY를 없애고 데이터에 구조를 생각해봅니다. START_YYYYMM = 190001 END_YYYYMM = 199912
1세기이므로 0~99년이라는 것을 생각하여 년의 왼쪽에서 2자리를 없앱니다. START_YYMM = 0001 END_YYMM = 9912
년과 월의 배치를 바꾸면 연속된 범위를 얻을 수 있습니다. START_MMYY = 0100 END_MMYY = 1299
MMYY에서 데이터의 구조를 바꾸기 전의 YYYY을 얻으려면 MMYY에서 YY를 가져와야 하므로 MM을 없애야 합니다. MM은 천의자리와 백의자리 수이기 때문에 100으로 나누고 나머지를 가져옵니다. 거기에 1900을 더하면 YYYY를 얻을 수 있습니다. YEAR = (MMYY%100)+1900
MMYY에서 MM을 얻으려면 100으로 나눈 결과에서 정수를 가져옵니다. MONTH = MMYY//100
python3에서 범위 range는 미만이므로 1299를 range에 넣을 때 1300으로 넣습니다. range(100, 1300) python3에서 datetime.date(YYYY,MM,DD)는 년월일입니다. python3에서 date.weekday()는 일요일인 경우 6을 반환합니다. python3에서 str.count("6")은 "6"의 개수를 셉니다.
python3 20세기(1901~2000)
풀이1
import calendar
print(str([calendar.monthrange(y,m)[0] for y in range(1901,2001) for m in range(1,13)]).count("6"))
풀이2
import datetime
print(str([datetime.date(y,m,1).weekday() for y in range(1901,2001) for m in range(1,13)]).count("6"))
from datetime import datetime, timedelta
def f(start, end):
ct = datetime(start, 1, 1)
res = 0
while ct.year <= end:
res += (1 if ct.day==1 and ct.weekday()==6 else 0)
ct += timedelta(days=1)
print(res)
if __name__ == '__main__':
f(1900, 1999)
파이썬 3.6.2 64
파이썬 3.6
# 최초 일요일이 1900.1.7
# 매월 1일의 누적일수가 7로 나누어 떨어지면 일요일
case_a = [31,28,31,30,31,30,31,31,30,31,30,31] # 평년
case_b = [31,29,31,30,31,30,31,31,30,31,30,31] # 윤년
monthlydate,datesum,count = [],0,0
for year in range(1900,2000):
if year%4 == 0:
if year%100 == 0 and year%400 != 0: monthlydate = case_a
else: monthlydate = case_b
else: monthlydate = case_a
for date in monthlydate:
datesum += date
if (datesum-(date-1))%7 == 0: count += 1
print(count)
*결과값
172
# 파이썬
# 윤년들
leap_years = (
1904, 1908, 1912, 1916, 1920,
1924, 1928, 1932, 1936, 1940,
1944, 1948, 1952, 1956, 1960,
1964, 1968, 1972, 1976, 1980,
1984, 1988, 1992, 1996, 2000)
# 0 월요일 ~ 6 일요일
not_leap = (0, 3, 3, 6, 1, 4, 6, 2, 5, 0, 3, 6) # 1월~12월 1일의 1월 1일 대비 요일
leap = (0, 3, 4, 0, 2, 5, 0, 3, 6, 1, 4, 0) # 윤년의 경우
# first=1일들의 요일 값 리스트, until=2000년까지 시행, year=1900 현재 년도, r= 1일들의 일요일 갯수)
def month_1st_sun(first=list(not_leap), until=2000, year=1900, r=0):
if r == 0:
return month_1st_sun(first, until, year=1901, r=3)
# 작년의 1월 1일을 가져온 다음 작년의 윤년 여부, 올해의 윤년 여부에 따라 올해의 1일들을 구합니다.
start = first[0]
if year in leap_years:
for m in range(12):
first[m] = leap[m] + start + 1
elif year-1 in leap_years:
for m in range(12):
first[m] = not_leap[m] + start + 2
else:
for m in range(12):
first[m] = not_leap[m] + start + 1
# 올해의 1일들을 7로 나눈 나머지로 바꾸고 값이 6인 달들 수 만큼 결과값(r)을 더합니다.
for m in range(12):
first[m] = first[m]%7
if first[m] == 6:
r += 1
# 2000년까지 세고 난 후 종료합니다.
if year == until:
return r
else:
year += 1
return month_1st_sun(first, until, year, r)
print(month_1st_sun()) # 172
def sunday(n,a,b):
result = 0
day = n
common = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
leap = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
for i in range(a, b+1):
if a%400 == 0:
for j in leap:
day += j
if day%7 == 0:
result += 1
elif a%100 == 0:
for j in common:
day += j
if day%7 == 0:
result += 1
elif a%4 == 0:
for j in leap:
day += j
if day%7 == 0:
result += 1
else:
for j in common:
day += j
if day%7 == 0:
result += 1
day = day%7
return result
print(sunday(1,1900,1999))
print(sunday(2,1901,2000))
import calendar
count = 0
for year in range(1900, 2000):
for month in range(1, 13):
if calendar.monthrange(year, month)[0] == 6:
count = count + 1
print('20세기에서 매월 1일이 일요일인 경우는 %d입니다' % count)
Python 3의 calendar 라이브러리를 사용한 풀이입니다.
Python
currDay = 0 #1 = 월요일, 일요일 = currDay의 나머지가 0일때
ans = 0
for year in range(1901, 2001):
leapYear = False
if year%4 == 0:
leapYear = True
if year%100 == 0:
leapYear = False
if year%400 == 0:
leapYear = True
for month in range(1, 13):
finalDay = 32
if month in [4, 6, 9, 11]:
finalDay = 31
if month == 2:
if leapYear is True:
finalDay = 30
else:
finalDay = 29
for day in range(1, finalDay):
currDay += 1
if currDay%7 == 0 and day == 1:
ans += 1
print(ans)
def absdate(n):
n = str(n)
em = [31,28,31,30,31,30,31,31,30,31,30,31]
Y,M,D = map(int,[n[:4],n[4:6],n[6:]])
Yd = 365*abs(Y - 1601)+abs(Y - 1601)//4+abs(Y - 1601)//400-abs(Y - 1601)//100
Md = sum(em[:M-1])+ ( 1 if M>2 and Y%4==0 and (Y%400==0 or Y%100!=0) else 0 )
Dd = D-1
return Yd+Md+Dd
sunday = absdate(19000107)
print([(absdate(str(i)+str(j).zfill(2)+'01') - sunday)%7 for i in range(1900,2000)
for j in range(1,13)].count(0))
package test;
import java.time.LocalDate;
public class test {
public static void main(String[] args) {
LocalDate date = LocalDate.of(1900, 1, 1);
int count = 0;
while (date.getYear() < 2000) {
date = date.plusMonths(1);
count += date.getDayOfWeek().getValue() == 7 ? 1 : 0;
}
System.out.println(count);
}
}
Ndays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
Ndays_y = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
days = []
tot = 0
cnt = 0
for year in range(1900, 2000):
if year % 4 == 0:
if year % 100 == 0 and year % 400 != 0: days += Ndays
else: days += Ndays_y
else: days += Ndays
for i in range(len(days)):
if i == 0: tot = 1
else: tot += days[i-1]
if tot % 7 == 0: cnt += 1
print(cnt)
답 : 172
mths = [31,28,31,30,31,30,31,31,30,31,30,31]
year,i,c = 1901,2,0
while year < 2000:
for x in mths:
if i == 0:
c += 1
i = (i+x+(0,1)[x == 28 and year%4 == 0 or (year%100 == 0 and year%400 == 0)])%7
year += 1
print(c)
import datetime
sunday = 0
c = datetime.datetime(1901, 1, 1)
d = datetime.timedelta(days = 1)
while c.year < 2001:
if c.day == 1 and c.weekday() == 6:
sunday += 1
c += d
print(sunday)
def count_sunday(start,end):
dayofweek=['월','화','수','목','금','토','일']
month={1:31,2:28,3:31,4:30,5:31,6:30,7:31,8:31,9:30,10:31,11:30,12:31}
num=0
cnt=0
#년도
for i in range(start,end):
#윤년인 경우, 2월 값 29일로 변경
if(i%4==0and i%100!=0) or (i%100==0 and i%400==0):
month[2]=29
else:
month[2]=28
#월
for j in range(1,13):
if dayofweek[num]=='일':
cnt+=1
#다음달 1일에 해당되는 요일 위치값
num=(num+month[j])%7
return cnt
public class 이십세기에서매월1일이일요일인경우의개수 {
public static void main(String[] args) {
Calendar cal = Calendar.getInstance();
int count=0;
for(int i=1900; i<2000; i++) {
cal.set(Calendar.YEAR, i);
for(int j=0; j<12; j++) {
cal.set(Calendar.MONTH, j+1);
cal.set(Calendar.DAY_OF_MONTH, 1);
int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
String kDayOfWeek = "";
switch(dayOfWeek) {
case 1:
kDayOfWeek = "일";
count++;
break;
/*case 2:
kDayOfWeek = "월";
break;
case 3:
kDayOfWeek = "화";
break;
case 4:
kDayOfWeek = "수";
break;
case 5:
kDayOfWeek = "목";
break;
case 6:
kDayOfWeek = "금";
break;
case 7:
kDayOfWeek = "토";
break;*/
default:
break;
}
}
}
System.out.println(count);
}
}
month = [31,28,31,30,31,30,31,31,30,31,30,31]
day_list =[]
count = 0
k=0
for n in range(1900,2000):
if n % 400 != 0 and n%100 ==0 :
month[1] = 28
elif n % 400 == 0 or n % 4 ==0:
month[1] = 29
for m in range(0,12):
for d in range(1,month[m]+1):
day_list.append(d)
for i in day_list:
k +=1
if i == 1 and (k)%7==0:
count+=1
print(count)
def sunday(sy, ey):
sun_cnt = 0
day = 0
leaf_year = lambda year: (year % 4 == 0 and year % 100 != 0) or year % 400 == 0
for year in range(sy, ey+1): # 연도
days = [31, 28 + leaf_year(year), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
for dpm in days: # 월
while day < dpm:
day += 7
day = day - dpm
if day == 1:
sun_cnt += 1
return sun_cnt
if __name__ == '__main__':
starY = 1900
endY = 1999
print(sunday(starY, endY))
def sunday_count():
datecount=0
suncount=1
Mdate=[]
for i in range(1900,2000):
for j in range(1,13):
if j in [1,3,5,7,8,10,12]:datecount+=31
elif j in [4,6,9,11]:datecount+=30
else:
if i%4==0 and i!=1900:datecount+=29
else:datecount+=28
if (datecount)%7==6:
suncount+=1
if j==12:Mdate.append((i+1,1,1))
else:Mdate.append((i,j+1,1))
print(suncount,'\n',Mdate)
if __name__ == "__main__":
sunday_count()
import calendar
count = 0
daymon = [calendar.monthrange(i,k) for i in range(1900,2000) for k in range(1,13)]
for i in range(len(daymon)):
if daymon[i][0] == 6:
count += 1
print(count)
def count_sunday():
y=1
m=1
d=1
count=0
mon={4:30,6:30,9:30,11:30,2:28}
mon_e={4:30,6:30,11:30,9:30,2:29}
while y<=100:
while m<=12:
if (y%4!=0 or y%100==0) and y%400!=0:
use=mon
else:
use=mon_e
if use.get(m)==None:
d+=31
m+=1
else:
d+=use[m]
m+=1
if d%7==0:
count+=1
m=1
y+=1
return count
print(count_sunday())
import datetime
start = datetime.date(1900,1,1)
delta = datetime.timedelta(1)
count = 0
while start <= datetime.date(1999,12,31):
if start.day == 1 and start.weekday() == 6:
count += 1
start += delta
print(count)
def time(year_1, month_1, date_1, year_2, month_2, date_2):
year = year_1
month = month_1
date = date_1
day_idx = 0
day_list = ['MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT', 'SUN']
date_30 = [4, 6, 9, 11]
cnt = 0
while True:
if month == 2:
if year % 4 == 0:
if year % 400 != 0 and year % 100 == 0:
date_last = 28
elif year % 400 == 0:
date_last = 29
else:
date_last = 29
else:
date_last = 28
elif month in date_30:
date_last = 30
else:
date_last = 31
if month == 12 and date == date_last:
year += 1
month = 1
date = 1
if day_idx == 6:
day_idx = 0
else:
day_idx += 1
day = day_list[day_idx]
elif date == date_last:
month += 1
date = 1
if day_idx == 6:
day_idx = 0
else:
day_idx += 1
day = day_list[day_idx]
else:
date += 1
if day_idx == 6:
day_idx = 0
else:
day_idx += 1
day = day_list[day_idx]
if date == 1 and day == 'SUN':
cnt += 1
print('{} / {} / {} / {}'.format(year, month, date, day))
if year == year_2 and month == month_2 and date == date_2:
print('COUNT : {}'.format(cnt))
break
if __name__ == '__main__':
time(1900,1,1,1999,12,31)
sum_day =0
cnt =0
for year in range(1900,2001):
for month in range(1,13):
for day in range(1,32):
sum_day +=1
if day==1 and sum_day%7==0:
cnt+=1
if (month==1 or month==3 or month==5 or month==7 or month==8 or\
month==10 or month==12) and day ==31:
break
elif (month==4 or month==6 or month==9 or month==11) and day ==30:
break
elif month==2 and year%4 ==0 and year%400==0 and day==29:
break
elif month==2 and year%4 ==0 and year%400!=0 and day==28:
break
print(cnt)
월별 조건에 따라 year,month,day 를 반복시키고 총 일수는 따로 카운팅해줬어요 이떄 월별 말일조건에 따라서 달이 바뀔때가 곧 매월의 1일 이므로, 이때 총일수(sum_day)가 7의 배수일떄가 일요일입니다. 그 경우의 수를 cnt를 통해 세어주었습니다
// Rust
// 결국 윤년은 (4로 나누어지되 100으로 나누어지지 않거나) or (400으로 나눠지는) 연도입니다 : (%4 && !%100) || (%400)
use std::collections::HashMap; fn sundays() -> HashMap<(usize, usize), usize>{
let mut map = HashMap::new();
map.insert((1900, 1), 1); // Mon 1
let m30 = [4, 6, 9, 11];
let m31 = [1, 3, 5, 7, 8, 10, 12];
for year in 1900..=1999 {
for month in 1..=12 { //다음 달 1일의 요일 계산
let days;
if m31.contains(&month) {
days = 31;
} else if m30.contains(&month) {
days = 30;
} else if year % 400 == 0 || (year % 4 == 0 && year % 100 != 0) {
days = 29;
} else {
days = 28;
}
if month == 12 {
map.insert((year+1, 1),
(map[&(year, month)] + days) % 7);
} else {
map.insert((year, month+1),
(map[&(year, month)] + days) % 7);
}
}
}
map
}
fn t() {
assert_eq!(sundays().values().filter(|&v| *v==0).count(), 172);
}
import datetime
day = datetime.datetime.strptime('1900/01/01', "%Y/%m/%d")
target = datetime.datetime.strptime('1999/12/31', "%Y/%m/%d")
diff_days = datetime.timedelta(days=1)
count = 0
while day < target:
if day.weekday() == 6 and day.day == 1:
count += 1
day += diff_days
print(count)
using System;
namespace solution
{
public enum weeks{ Monday, Tuesday, Wdnesday, Thursday, Friday, Saturday, Sunday}
class Program
{
static void Main(string[] args)
{
int cnt = 0;
int w = 6 - 31;
for (int y = 1900; y < 2000; y++)
{
int[] days = {31, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30 };
if (isLeaf(y))
days[2] = 29;
for (int m = 1; m <= 12; m++)
{
w = (w + days[m - 1]) % 7;
if (w == 6)
cnt++;
}
}
Console.WriteLine(cnt);
}
private static bool isLeaf(int y)
{
if (y % 400 == 0 && y % 100 != 0 && y % 4 == 0)
return true;
return false;
}
}
}