我正在解决Project Euler#19:
在二十世纪的第一个月(1901年1月1日至2000年12月31日),有多少个星期日下降?
以下是代码:
months = { "January": 31,
"February" : 28,
"March" : 31,
"April" : 30,
"May" : 31,
"June" : 30,
"July" : 31,
"August" : 31,
"September" : 30,
"October" : 31,
"November" : 30,
"December" : 31}
def countingSundays():
day = 1
sunday_count = 0
for year in xrange(1901,2001):
for m in months:
day += months[m]
if year % 4 == 0 and m == "February":
day += 1
if day % 7 == 0:
sunday_count += 1
print "Sundays:", sunday_count
程序的输出是172,这是不正确的。 我搜索的答案是171。 所以我想知道为什么我得到额外的1周日?
答案 0 :(得分:3)
你正在迭代months
dict,期望它按照月份的顺序进行迭代,但是不会对dicts进行排序,因此你可以按错误的顺序获取月份。 / p>
由于您实际上并不需要月份名称,因此您只需将months
列为月份长度即可。
答案 1 :(得分:1)
您应该使用datetime
库,它将自动处理所有闰年信息:
from datetime import date
from collections import Counter
counter = Counter()
for year in xrange(1901, 2001):
for month in xrange(1, 13):
day = date(year, month, 1)
counter[day.weekday()] += 1
print counter[6]
答案 2 :(得分:1)
import time
from math import floor
"""
Gaussian algorithm to determine day of week
"""
def day_of_week(year, month, day):
"""
w = (d+floor(2.6*m-0.2)+y+floor(y/4)+floor(c/4)-2*c) mod 7
Y = year - 1 for January or February
Y = year for other months
d = day (1 to 31)
m = shifted month (March = 1, February = 12)
y = last two digits of Y
c = first two digits of Y
w = day of week (Sunday = 0, Saturday = 6)
"""
d = day
m = (month - 3) % 12 + 1
if m > 10: Y = year - 1
else: Y = year
y = Y % 100
c = (Y - (Y % 100)) / 100
w = (d + floor(2.6 * m - 0.2) + y + floor(y/4) + floor(c/4) - 2*c) % 7
return int(w)
"""
Compute the number of months starting on a given day of the week in a century
"""
def months_start_range(day,year_start,year_end):
total = 0
for year in range(year_start, year_end + 1):
for month in range(1,13):
if day_of_week(year, month, 1) == day: total += 1
return total
start = time.time()
total = months_start_range(0,1901,2000)
elapsed = time.time() - start
print("%s found in %s seconds") % (total,elapsed)
这可能会解决问题。
解决它需要大约0.068秒。
答案 3 :(得分:1)
这里是解决此问题的另一种方法
public static void main(String[] args) {
int k = 0;
// String months[] = { "January", "February", "March", "April", "May", "June",
// "July", "August", "September",
// "October", "November", "December" };
String Days[] = { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" };
int MonthsDdays[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
int counter = 0;
for (int t = 1900; t <= 2000; t++) {
MonthsDdays[1]=28;
if (t % 4 == 0) {
if (t % 100 == 0)
{
if (t % 400 == 0)
MonthsDdays[1] = 29;
} else if (t % 100 != 0)
MonthsDdays[1] = 29;
}
int p = 0;
while (p < 12) {
for (int j = 0; j < MonthsDdays[p]; k++, j++) {
if (k == 7)
k = 0;
if (Days[k].equalsIgnoreCase("Sunday") && j == 0 && t > 1900) {
counter++;
}
}
p++;
}
}
System.out.println(counter);
}
答案 4 :(得分:0)
你犯的错误:
正确的计划是:
from collections import OrderedDict
months = OrderedDict( [("January",31),("February", 28),("March",31),
("April", 30), ("May", 31), ("June", 30),
("July", 31), ("August", 31), ("September", 30),
("October", 31), ("November", 30), ("December", 31)] )
days = ['Tuesday','Wednesday', 'Thursday','Friday','Saturday', 'Sunday', 'Monday']
day = 0
sunday_count = 0
def isLeap(year): #https://en.wikipedia.org/wiki/Leap_year#Algorithm
leap = True
if year % 4 != 0:
leap = False
elif year % 100 != 0:
leap = True
elif year % 400 != 0:
leap = False
return leap
for year in xrange(1901,2001):
leap = isLeap(year)
for m in months:
dayName = days[day%7]
if dayName == "Sunday":
sunday_count += 1
#print year, m, dayName
day += months[m]
if leap == True and m == "February":
day += 1
print sunday_count
# print 171
另外,有些日子:
1901 January Tuesday
1901 February Friday
1901 March Friday
1901 April Monday
1901 May Wednesday
1901 June Saturday
1901 July Monday
1901 August Thursday
1901 September Sunday
...
答案 5 :(得分:0)
import pandas as pd
from datetime import date
start = date(1901, 1, 1)
end = date(2000, 12, 31)
d = pd.date_range(start, end, freq='MS').strftime('%A')
s = pd.Series(d)
print(s.value_counts())
答案 6 :(得分:0)
所以我从日期的角度来看这个问题,而不是计算天数。 这是我的解决方案:
days_1st = list()
day_counter = 1
for year in range(1900, 2001):
for month in range(1,13):
#Skip for year 1900 as count starts from 1901, but this still
#adds the days hence keeping the cycle in sync!
if year != 1900:
days_1st.append(day_counter)
if month == 4 or month == 6 or month == 9 or month == 11:
day_counter+=30
elif month == 2 and ((year % 100 == 0 and year % 400 == 0) or (year % 100 != 0 and year % 4 == 0)):
day_counter+=29
elif month == 2:
day_counter+=28
else:
day_counter+=31
# mod 7 because since the day the counting started (1 Jan 1900 -
# Monday) Every 7th day is a sunday!
days_sunday = list(filter(lambda x: x % 7 == 0, days_1st))
print(len(days_sunday))
答案 7 :(得分:0)
尽管我们可以使用日历功能,但我尝试了数学方法。 我首先计算了月份的数学运算,以确定使用其他月份的月份的第一天之间的关系。另外,为简化计算leap年,我计算了从3月到2月的年份。如果要计算1901年1月和2月,则可以编写一个单独的条件,并执行相同的操作以删除2001年1月和2月。但是,在这种情况下,它们并不重要,因为它们不是星期日,因此您可以删除此特定情况的最后一个if条件。
# Zero is Sunday and the rest of the days are according to mod7
# li stores the first days of the months in the year in every iteration
# The year in initial li is 1900 but the contents are Mar-1900 to Feb-1901
# At the end, we can check if Jan or Feb of 2001 contain a Sunday and remove if it does
li, cnt = [4,0,2,5,0,3,6,1,4,6,2,5], 0
# Could also initialize li from by the same method as below, but I had already calculated those
# cnt adds number of zeros in every iteration (the number of Sundays in every year) to its value
# As we don't count for the year 1900 cnt=0, else initialize cnt=li.count(0)
for year in range(1901,2001):
if year%4==0:
li[0]=li[8]=(li[11]+1)%7 #Set March and November to +1 value than last Feb
else:
li[0]=li[8]=li[11] #Set March and November to same value as last Feb
# The following values of other months will depend solely on their own March value
# You can check the Math if you want to
li[3]=li[11]=(li[0]+1)%7;li[6]=li[9]=(li[0]+2)%7;li[1]=li[4]=(li[0]+3)%7;li[2]=li[10]=(li[0]-2)%7;li[5]=(li[0]-1)%7;li[7]=(li[0]-3)%7
cnt = cnt + li.count(0)
# This is to remove the extra two months of the year 2001 if they bother the answer
if li[10] == 0 or li[11] == 0:
cnt = cnt-1
print(cnt)
这是我对StackOverflow的第一个答案,希望我写得不错。 ;-)
答案 8 :(得分:0)
A = [31,28,31,30,31,30,31,31,30,31,30,31]
sunday =0
gK = 1
for y in range(1901,2001):
if(y %4 ==0):
A[1] = 29
else:
A[1] = 28
for m in range(len(A)):
for d in range(1,A[m]+1):
if(gK ==6):
if(d==1):
sunday +=1
gK =0
else:
gK =gK+1
print(sunday)
答案 9 :(得分:0)
==> Python解决方案
euler19.py
normal_year = [31,28,31,30,31,30,31,31,30,31,30,31]
leap_year = [31,29,31,30,31,30,31,31,30,31,30,31]
years = [ normal_year ] * 100
for i in range(3, len(years), 4) :
years[i] = leap_year
current_day = (0+365) % 7
sundays = 0
for y in years :
for m in y :
if current_day % 7 == 6:
sundays += 1
current_day += m%7
print (sundays)
答案 10 :(得分:0)
我想我得到了答案。不过,我不确定。您的逻辑是否正确。但是需要一点改进。首先,我们需要首先计算星期二的数量,因为我们清楚地知道这是1900年1月1日,星期一。
months = { "January": 31,
"February" : 28,
"March" : 31,
"April" : 30,
"May" : 31,
"June" : 30,
"July" : 31,
"August" : 31,
"September" : 30,
"October" : 31,
"November" : 30,
"December" : 31}
for month in months:
print(months[month])
tuesday_count = 0
day = 0
extra_days = 0
for year in range(1901, 2001):
days_in_the_year = 0
for month in months:
day += months[month]
days_in_the_year += months[month]
if( year % 4 == 0 and month == 'February'):
if (year % 100 != 0):
extra_days += 1
days_in_the_year += 1
day += 1
elif(year % 100 ==0 and year % 400 ==0):
extra_days += 1
days_in_the_year += 1
day += 1
if( (day) % 7 == 0):
tuesday_count += 1
print('No. of days in the year',year,'are',days_in_the_year)
print('No. of Tuesdays counted so far is =', tuesday_count)
print('The number of extra_days because of the leap years are:',extra_days)
# print('extra_days % 7 =', '25 % 7 =', extra_days % 7)
print('So, there were', extra_days // 7, 'extra_no_of_weeks left that we haven\'t considered. After that, it\'s followed by --wed, thu, fri and sat (we don\'t need to consider that).\n So, the total number of Tuesdays are', tuesday_count+3 )
tuesday_count += 3
print('This means only 2 Sundays that have followed')
sunday_count = tuesday_count - 1
print('Since, 1901 Jan1 would be a Tuesday, we need to subract one from the total number of Sundays\n So, the total number of sundays are:', )
sunday_count=sunday_count-1
print(sunday_count)
答案 11 :(得分:0)
months=[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]
sundays=0
start=2
for y in range(25):
for nonleap in range (3):
for j in months:
start=(start+j)%7
if start == 0:
sundays+=1
for m in leap:
start=(start+m)%7
if start == 0:
sundays+=1
print sundays
答案 12 :(得分:0)
请注意,问题将1900年的第一天定义为星期一,而您将1901年的第一天定义为星期一。
months = [31,28,31,30,31,30,31,31,30,31,30,31]
def countingSundays():
day = 1
sunday_count = 0
for year in range(1900,1901):
for m in months:
day += m
if (year % 4 == 0 and m == 28):
day += 1
for year in range(1901,2001):
for m in months:
day += m
if (year % 4 == 0 and m == 28):
day += 1
if day % 7 == 0:
sunday_count += 1
return sunday_count
print ("Sundays:", countingSundays())
答案 13 :(得分:0)
您已将day变量初始化为1,但1901年1月1日是星期二。我犯了同样的错误;-)