PHP interview task: one week calculation

Source: Internet
Author: User
Not long ago, someone gave me an interview task. I am writing a function to push and export any calendar (or even a fictitious calendar) that is based on a standard week working for seven days. I know the frequency of a leap year. if so, how many months a year has, the number of days each month.

Not long ago, someone gave me an interview task. I am writing a function to push and export any calendar (or even a fictitious calendar) that is based on a standard week working for seven days. I know the frequency of a leap year. if so, how many months a year has, the number of days each month.

This is a fairly common introductory job-interview task. in this article, I will solve and explain the mathematics behind it. I am not as casual as throwing away simplified and corrected me-I believe I am an unnecessary complex. This article will present two aspects that are close to the problem-one that can make your spirit so dynamic (impress your friends, I guess ?), And a computer is more friendly (less code lines, more ).

The calendar definition is as follows:

  • There are 13 months each year
  • Even every month for 21 days, every strange month for 22
  • 13 months lack one day, each leap year
  • A leap year is any divisible by 5
  • 7 days per week: Sunday, Monday, Tuesday, Wednesday, Thursday, Saturday

The task is as follows:

Considering that the first day of January 1, 1900 is Monday, writing a function will print the week of the given date. In the example, enter {: 17, month: 11: 2013} to output "Saturday ".

For the rest of this article, I will use the following date format: dd. mm. Yyyy, because it is meaningful.

Preparation

Before starting any smart risks, it is important to have an appropriate environment setting to avoid wasting time preparing in advance. I always recommend that you enter the encoding interview task to be eager to try the development environment, you can test your code in a moment of attention.

Create a new folder that contains two subfolders: classes and public. Yes, this is a one-time task. it can solve a simple program function, but I like it thoroughly. You will understand why.

In the classes sub-folder, create an empty PHP class CalendarCalc. php. In the public subfolder, create a file index. php with the following content:

 

If you can open "Hello" in your browser, you are ready to start.

CalendarCalc initialization

To make things easier to verify and imagine, I created a demo method to print the entire calendar from 1.1.1900. 22.13.2013. This allows us to easily check our computing functions. However, the initialization class is the same:

  iNumDays = count($this->aDays);        $this->iStartDayIndex = array_search('Monday', $this->aDays);        $this->aInput = array('d' => $day, 'm' => $month, 'y' => $year);    }    public function demo() {    }}

Let's explain the protected attributes.

$ ADays is an array. Define it to ensure that there is a digital index allocation per week-a crucial day after the week is determined. We cache its length $ iNumDays property. This allows us to extend the array in the days to come, if we choose -- another task may ask for the same calculation, but it is mentioned that this week may have been more or less more than 7 days.

$ IStartDayIndex is the index on Monday (in this example) because Monday (1.1.1900) is defined as in the task description. When we start the index for one day, we can use it to offset the computing result to get the real week. You will understand what I mean.

$ AInput is an array to save input values. When we instantiate CalendarCalc, we want to know the day of the week through the date value. This property stores these values for every time we come up with the calc method, so that we don't need them, or worse, repeat them in another function call. The logic $ aInput, $ iStartDayIndex and $ iNumDays are in the _ construct method.

Other attributes are self-evident.

Now, fill in the demo () method with the following content:

public function demo() {        $demoYear = $this->startYear;        $totalDays = 0;        while ($demoYear < 2014) {            echo "$demoYear
  
  
   
   ";            $demoMonth = 1;            while ($demoMonth < 14) {                echo "
   
   "; echo " 
    "; $dayCount = ($demoMonth % 2 == 1) ? 22 : 21; $dayCount = ($demoMonth == 13 && $demoYear % 5 == 0) ? 21 : $dayCount; $demoDay = 1; echo " 
    
      "; while ($demoDay <= $dayCount) { $index = ++$totalDays % 7; if ($demoDay == 1) { for ($i = 0; $i < $index-1; $i++) { echo " 
     "; } if ($index == 0 || $index == 7) { $i = 6; while ($i--) { echo " 
     "; } } } echo " 
     "; if ($index == 0) { echo " 
    
      "; } $demoDay++; } echo " 
    "; $demoMonth++; } echo " 
   
Month $demoMonth
Monday Tuesday Wednesday Thursday Friday Saturday Sunday
$demoDay
"; $demoYear++; } }

Don't bother trying to understand this method-it's totally unimportant. This is just to help us verify the work, and according to the second solution is actually part of what we will present in this article.

Changed content index. Php file:

  demo();

... Open it in the browser. You should see a calendar output with 1:

We now have a check result 17.11.2013 truth (note the date. It is indeed Saturday ).

Spiritual Approach

The mental calculation is actually very simple. First, we need the number of bases between the leap year date and the given date. 1900 is divided by 5, which is itself a leap year. The number of hops is therefore the difference between the date input date and base, divided by 5, rounding (only the full run year statistics, naturally), 1900 plus one. Create a new method CalendarCalc called calcFuture and give it this content:

$iLeaps = floor(($this->aInput['y'] - $this->startYear) / $this->leapInterval + 1);

We were even told that there were 21 days each month and 22 strange months:

1 => 22
2 => 21
3 => 22
4 => 21
5 => 22
6 => 21
7 => 22
8 => 21
9 => 22
10 => 21
11 => 22
12 => 21
13 => 22 (or 21 in the leap year)

The total number of days is one year. Therefore, 280 or 279 is in a leap year. If our modulo 7 280%, 0, because 280 is divisible by 7. In a leap year, the model is 6.

This means that the annual calendar starts on the same day, except for the leap year, when it starts that day, the first day of the previous year. Therefore, if 1.1.1900. Monday:

  • 1.1.1901. Monday
  • 1.1.1902. Sunday
  • 1.1.1903. Sunday
  • 1.1.1904. Sunday
  • 1.1.1905. Saturday
  • 1.1.1906. Saturday
  • ...

Based on this, we can calculate the number of daily actions until our input. We knew we had 23 jumps until the input date (2013), and we moved back 23 times a day. 23% of the modulo 7 is 2, which means we have successfully completed 3 times and then two days (which is offset) -- 1.1.2013. It's Saturday. Check the demo calendar and check yourself.

Let's first understand the code. Leap line or above, and then add the following:

$iOffsetFromCurrent = $iLeaps % $this->iNumDays;        $iNewIndex = $this->iStartDayIndex - $iOffsetFromCurrent;        if ($iNewIndex < 0) {            $iFirstDayInputYearIndex = $this->iStartDayIndex + $this->iNumDays - $iOffsetFromCurrent;        } else {            $iFirstDayInputYearIndex = $iNewIndex;        }

First, we calculate the offset. Then, when we calculate the new index array of the day, it depends on whether the new index is positive. This gives us the day of the week to enter the beginning of the year.

We also know that X starts from the day and month of every month X and 21st day of next month, because 21% 7 = 0. However, in the odd few months, the day before the start (22% 7 = 1 ). Therefore, if January starts from Saturday, February starts from Sunday, Sunday March, April, Monday, and so on. We come to the conclusion that every strange month has passed the year before the beginning of this year until we enter the date of the day January 1 with advanced indexes. We were in February November, so it was strange that there were five months. New offset + 5 or in our case, July 22, November 2013, and Thursday. Let's turn it into code immediately in the front line.

$iOddMonthsPassed = floor($this->aInput['m'] / 2);$iFirstDayInputMonthIndex = ($iFirstDayInputYearIndex + $iOddMonthsPassed) % $this->iNumDays;

The rest is to see the day we entered from the beginning of this month.

$iTargetIndex = ($iFirstDayInputMonthIndex + $this->aInput['d']-1) % $this->iNumDays;return $this->aDays[$iTargetIndex];

We add a minus day (because the day has not passed !), 7 days. The number we get is our target index, which reliably gives us Saturday.

From now on, the entire calcFuture method CalendarCalc is like this:

/**     * A more "mental" way of calculating the day of the week     * @return mixed     */    public function calcFuture() {        $iLeaps = floor(($this->aInput['y'] - $this->startYear) / $this->leapInterval + 1);        $iOffsetFromCurrent = $iLeaps % $this->iNumDays;        $iNewIndex = $this->iStartDayIndex - $iOffsetFromCurrent;        if ($iNewIndex < 0) {            $iFirstDayInputYearIndex = $this->iStartDayIndex + $this->iNumDays - $iOffsetFromCurrent;        } else {            $iFirstDayInputYearIndex = $iNewIndex;        }        $iOddMonthsPassed = floor($this->aInput['m'] / 2);        $iFirstDayInputMonthIndex = ($iFirstDayInputYearIndex + $iOddMonthsPassed) % $this->iNumDays;        $iTargetIndex = ($iFirstDayInputMonthIndex + $this->aInput['d']-1) % $this->iNumDays;        return $this->aDays[$iTargetIndex];    }
Machine-friendly mode

Perhaps a simpler method is to calculate the number of days, which has been offset by the basic date, modulo, 7, and. Not many people can calculate the size of a number, but that is why it is more machine-friendly.

Again, we need to jump:

public function calcFuture2() {    $iTotalDays = 0;    $iLeaps = floor(($this->aInput['y'] - $this->startYear) /    $this->leapInterval + 1);}

Then, consider the year. After several years of 280, the number of hops minus one day, plus one, because this year is still in progress.

$iTotalDays = (280 * ($this->aInput['y'] - $this->startYear)) - $iLeaps + 1;

Then, we add all the operations in the summary.

$iTotalDays += floor($this->aInput['m'] / 2) * 21 + floor($this->aInput['m'] / 2) * 22;

Finally, we add the input date, and then subtract the day because it is not passed yet:

$iTotalDays += $this->aInput['d'] - 1;        return $this->aDays[$iTotalDays % $this->iNumDays];

It's easy to die, isn't it?

Conclusion

If you see a life example computing, check it here. You can browse the directory to view the file in this URL, or you can download the complete source code, demo website, and the final CalendarCalc class from GitHub. The repurchase/demo is slightly better than the code provided in this article-some html5boilerplates are used to be more organized and enable ajax requests to check the date you entered as they, therefore, you do not need to reload the screen or regenerate the calendar to check the date each time.

If you have any improvement alternatives or suggestions, please make them in the following comments-as I said, I don't have any math talents. You are welcome to have the opportunity to learn more. For example, a person should consider the angle, Edge date, or date in the past to need more modifications to the original algorithm. I will leave this to you. Submit pull request at any time. you will get a shout out this article!

Hope you like this and learn new things! Wish you good luck in your interview!

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.