If you aren't already in the know, these ten problems are from the 2008 Winter Scripting games.

For each problem, I'm going to quickly sum up the interesting (interesting TO ME) bits of each problem, then I'm going to post the full source.

Event 4: Image is Everything

 

In this challenge, we are asked to pretty-print a calendar from text.

My solution is ugly. I don't make excuses, it's ugly. I don't know if I could have cleaned it up any without adding a lot of complexity/structure, so, this is honestly as pretty as I could make it in PowerShell.

Source

#PROBLEM #4
function Parse-Input ($monthYear)
{
    $split = $monthYear.Split("/");
    $month = [int][string]$split[0]
    $year = [int][string]$split[1]
   
    [datetime]"$year-$month-1"
}


$weekdayLabels = @("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat")
$weekdayToIndexMap = @{}
foreach ($index in 0..6) { $weekdayToIndexMap[$weekdayLabels[$index]] = $index }


function PrettyPrint-Calendar ($date)
{
    $output = @()
    $output += ""
    $output += $date.ToString("MMMM yyyy")
    $output += ""
    $output += [string]::Join("`t", $weekdayLabels)
    $output += PrettyPrint-DaysGrid -month $date
    Write-Host ($output | Out-String)
}


function Pad-Cell ($cell)
{
    $cell = $cell.ToString()
    if ($cell.length -eq 1)
    {
        " $cell"
    } elseif ($cell.length -eq 2) {
        " $cell"
    } else {
        "$cell"
    }
}


#POSTSCRIPT - I think everyone's solution for this was ugly, or maybe
#I'm just projecting. Projecting my opinion that "this code sucks and is ugly"
#out to everyone else's solution. Clearly it's not "elegant".
function PrettyPrint-DaysGrid ($month)
{
    #gets first day through last day of this month
    $days = 1..($month.AddMonths(1).AddDays(-1).Day)
   
    $daysOutput = @()
   
    $firstWeekdayIndex = $weekdayToIndexMap[$month.DayOfWeek.ToString().Substring(0,3)]
    $weekdayOffset = ($firstWeekdayIndex + 7 - 1) % 7
   
    foreach ($emptyDay in 0..($firstWeekdayIndex - 1))
    {
        $daysOutput += "`t"
    }
    foreach ($day in $days)
    {
        $weekday = ($day + $weekdayOffset) % 7
       
        if ($weekday -le 5)
        {
            $daysOutput += "$(Pad-Cell $day)`t"
        }
        else
        {
            $daysOutput += "$(Pad-Cell $day)`n"
        }
    }
   
    [string]::Join("", $daysOutput)
}


function Solve-Problem4
{
    #POSTSCRIPT-OOPS - Apparently I forgot that Read-Host takes in a "prompt" argument,
    #so I "innovated" and found an unnecessary workaround using Write-Host below! Go me!
    Write-Host -noNewLine "Please enter a date in M/YYYY format: "
   
    PrettyPrint-Calendar -date ( Parse-Input -monthYear (Read-Host) )
}




Solve-Problem4

2008 Winter Scripting Game Events: Index