Created
August 21, 2017 22:45
-
-
Save AndriiStefaniv/f3567e5f3f470a18daf36778da7d91f8 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
object Solution extends SolutionScope { | |
import Months.Month | |
def solution(y: Int, a: String, b: String, w: String): Int = { | |
implicit val calendar = new Calendar(y, Days.withName(w)) | |
val month1 = Months.withName(a) | |
val month2 = Months.withName(b) | |
val firstMonday = getFirstMonday(month1) | |
val lastSunday = getLastSunday(month2, calendar.getDays(month2)) | |
val daysBetween = diffInDays(firstMonday, lastSunday) | |
daysBetween / 7 | |
} | |
def getFirstMonday(month: Month, number: Int = 1)(implicit calendar: Calendar): DayOfYear = { | |
val day = calendar.getDayOfWeek(month, number) | |
if (day == Days.Monday) DayOfYear(number, month, day) | |
else if (number + 1 > calendar.getDays(month)) getFirstMonday(Months.nextMonth(month)) | |
else getFirstMonday(month, number + 1) | |
} | |
def getLastSunday(month: Month, number: Int)(implicit calendar: Calendar): DayOfYear = { | |
val day = calendar.getDayOfWeek(month, number) | |
if (day == Days.Sunday) { | |
DayOfYear(number, month, day) | |
} else if (number == 1) { | |
val previousMonth = Months.previousMonth(month) | |
getLastSunday(previousMonth, calendar.getDays(previousMonth)) | |
} else { | |
getLastSunday(month, number - 1) | |
} | |
} | |
def diffInDays(dayOfYear1: DayOfYear, dayOfYear2: DayOfYear)(implicit calendar: Calendar): Int = { | |
def diffInDaysAcc(current: DayOfYear, acc: Int): Int = { | |
if (current.month == dayOfYear2.month) acc + current.number | |
else { | |
val nextMonth = Months.nextMonth(current.month) | |
diffInDaysAcc(DayOfYear(calendar.getDays(nextMonth), nextMonth, Days.Sunday), acc) | |
} | |
} | |
diffInDaysAcc(dayOfYear1, calendar.getDays(dayOfYear1.month) - dayOfYear1.number) | |
} | |
} | |
trait SolutionScope { | |
case class DayOfYear(number: Int, month: Months.Month, day: Days.Day) | |
class Calendar(year: Int, firstDayOfWeek: Days.Day) { | |
import Months._ | |
private val isLeap: Boolean = year % 4 == 0 | |
private val daysPerMonth: Map[Month, Int] = Map( | |
January -> 31, | |
February -> (if (isLeap) 29 else 28), | |
March -> 31, | |
April -> 30, | |
May -> 31, | |
June -> 30, | |
July -> 31, | |
August -> 31, | |
September -> 30, | |
October -> 31, | |
November -> 30, | |
December -> 31 | |
) | |
def getDayOfWeek(month: Month, number: Int): Days.Day = { | |
if (month == Months.January && number == 1) firstDayOfWeek | |
else if (number == 1) | |
Days.nextDay(getDayOfWeek(Months(month.id - 1), getDays(Months(month.id - 1)))) | |
else Days.nextDay(getDayOfWeek(month, number - 1)) | |
} | |
def getDays(month: Month): Int = daysPerMonth(month) | |
} | |
object Months extends Enumeration { | |
type Month = Value | |
val January, February, March, April, May, June, July, August, September, October, November, | |
December = Value | |
def nextMonth(month: Month): Month = Months((month.id + 1) % Months.maxId) | |
def previousMonth(month: Month): Month = month match { | |
case January => December | |
case _ => Months(month.id - 1) | |
} | |
} | |
object Days extends Enumeration { | |
type Day = Value | |
val Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday = Value | |
def nextDay(d: Day): Day = Days((d.id + 1) % Days.maxId) | |
def previousDay(d: Day): Day = d match { | |
case Monday => Sunday | |
case _ => Days(d.id - 1) | |
} | |
} | |
} | |
object Main extends App { | |
println(Solution.solution(2014, "April", "May", "Wednesday")) | |
println(Solution.solution(2014, "April", "April", "Wednesday")) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment