Skip to content

Instantly share code, notes, and snippets.

@AndriiStefaniv
Created August 21, 2017 22:45
Show Gist options
  • Save AndriiStefaniv/f3567e5f3f470a18daf36778da7d91f8 to your computer and use it in GitHub Desktop.
Save AndriiStefaniv/f3567e5f3f470a18daf36778da7d91f8 to your computer and use it in GitHub Desktop.
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