DEV Community

dev.to staff
dev.to staff

Posted on

Daily Challenge #296 - Years to Centuries

The first century spans from the year 1 up to and including the year 100, The second - from the year 101 up to and including the year 200, etc. Return the century of the input year.

Examples

"1999" --> "20th"
"2011" --> "21st"
"2154" --> "22nd"
"2259" --> "23rd"
"1124" --> "12th"
"2000" --> "21st"
"20000" --> "210th"

Tests

8120
30200
1601
2020
3030
1900
1776

Good luck!


This challenge comes from Cpt.ManlyPink on CodeWars. Thank you to CodeWars, who has licensed redistribution of this challenge under the 2-Clause BSD License!

Want to propose a challenge idea for a future post? Email yo+challenge@dev.to with your suggestions!

Top comments (20)

Collapse
 
soorajsnblaze333 profile image
Sooraj (PS)
const toCentury = (year) => { const century = Math.ceil(year / 100); if (century.toString().length > 2) return year + " --> " + century + "th"; switch(century % 10) { case 1: return year + " --> " + century + "st"; case 2: return year + " --> " + century + "nd"; case 3: return year + " --> " + century + "rd"; default: return year + " --> " + century + "th"; } } 
Enter fullscreen mode Exit fullscreen mode
Collapse
 
alfredosalzillo profile image
Alfredo Salzillo

Clean and elegant!

Collapse
 
Sloan, the sloth mascot
Comment deleted
Collapse
 
soorajsnblaze333 profile image
Sooraj (PS)

But according to the math, 1 - 100 is 1st century. So I thought 1901 - 2000 is 20th century and 2001 - 2100 is 21st century. Is my understanding wrong ?

Collapse
 
mellen profile image
Matt Ellen-Tsivintzeli • Edited

"1066 --> 11st" should be 11th
"10266 --> 103th" should be 103rd

Collapse
 
_bkeren profile image
''

This question has conflicts.

"20000" --> "210th" (should it be 201st?)

In the question:

"The first century spans from the year 1 up to and including the year 100, The second - from the year 101 up to and including the year 200, etc. Return the century of the input year"

but toCentury(2000) -> 21st?

Collapse
 
mellen profile image
Matt Ellen-Tsivintzeli

Good question. I didn't notice that in the test cases.

Collapse
 
mrwebuzb profile image
Asliddinbek Azizovich • Edited

Here is my golang solution

 package main import ( "fmt" ) func getSuffix(number int) string { if number%100 >= 11 && number%100 <= 13 { return "th" } switch number%10 { case 1: return "st" case 2: return "nd" case 3: return "rd" } return "th" } func yearToCentury(year int) string { century := year / 100 return fmt.Sprintf("%d%s century", century+1, getSuffix(century+1)) } func main() { tests := []int{1999, 2011, 2154, 2259, 1124, 2000, 20000} for _, year := range tests { fmt.Printf("%d --> %s\n", year, yearToCentury(year)) } } 
Enter fullscreen mode Exit fullscreen mode
Collapse
 
mellen profile image
Matt Ellen-Tsivintzeli

what about the year 11122?

Collapse
 
mrwebuzb profile image
Asliddinbek Azizovich • Edited

I think, it will be 112nd century, because, current, 2020 year is inside of 21st century :)

Thread Thread
 
mellen profile image
Matt Ellen-Tsivintzeli

It should be 112th not 112nd, because 12 gets a th

Thread Thread
 
mrwebuzb profile image
Asliddinbek Azizovich

ohhhh, it was grammatically mistake, sorry

Collapse
 
cipharius profile image
Valts Liepiņš

Solution in Haskell:

import Numeric.Natural (Natural) toCentury :: Natural -> String toCentury = suffix . ceiling . (/ 100) . (+ 1) . fromIntegral where suffix x | x `mod` 10 == 1 = show x <> "st" | x `mod` 10 == 2 = show x <> "nd" | x `mod` 10 == 3 = show x <> "rd" | otherwise = show x <> "th" 
Collapse
 
willsmart profile image
willsmart • Edited

Here's a typescript implementation, and a ✨verbose-and-pretty✨ reference to check it against.
It's funny, but I take much more care with these little easy tasks than I used to. There's always more nuance than you expect and the implementations end up sitting at the bottom of your library being used for everything.

(btw, I tend to use ~~ as an alternative to of Math.floor because it's more succinct, and most often a little quicker)

function suffixForOrdinal(ordinal: number): string { return (~~(ordinal / 10) % 10 !== 1 && ['th', 'st', 'nd', 'rd'][ordinal % 10]) || 'th'; } function nameOfCentury(yearOrdinal: string | number): string { const centuryOrdinal = ~~((+yearOrdinal + 99) / 100); return `${centuryOrdinal}${suffixForOrdinal(centuryOrdinal)}`; } 

I'll check my working by comparing with a naive implementation that's more readable and hopefully reliable out of the gate...

// Stringifying the ordinal is an easier way to get individual the parts of the year... function suffixForOrdinal_slowButSure(ordinal: number): string { const ordinalString = String(ordinal), tens = +ordinalString.slice(-2, -1), ones = +ordinalString.slice(-1); if (tens == 1) return 'th'; // i.e. 11th, not 11st if (ones == 1) return 'st'; // 81st if (ones == 2) return 'nd'; // 82nd if (ones == 3) return 'rd'; // 83rd return 'th'; // anything else is 'th'. 45th } function nameOfCentury_slowButSure(yearOrdinal: string | number): string { // When extracting the century we need to be working with the index, not ordinal. // That's why the weirdness about 2000 -> 20th, 2001 -> 21st // (The year 2000 as an ordinal has index 1999) const yearIndex = +yearOrdinal - 1, yearIndexString = String(yearIndex), centuryIndex = +yearIndexString.slice(0, -2) || 0, centuryOrdinal = centuryIndex + 1; return `${centuryOrdinal}${suffixForOrdinal_slowButSure(centuryOrdinal)}`; } // Now do some 'testing' by comparing the implementations // This ensures that either both are right or both are wrong, // I'm pretty sure that the verbose one is as right as any static fixtures I could make. (function hareVsTortoise(startYearOrdinal = 1, endYearOrdinal = 100000) { for (let yearOrdinal = startYearOrdinal; yearOrdinal <= endYearOrdinal; yearOrdinal++) { if (nameOfCentury(yearOrdinal) !== nameOfCentury_slowButSure(yearOrdinal)) { console.error( `Conflicting answers for year ${yearOrdinal}:\n Hare: "${nameOfCentury( yearOrdinal )}"\n Tortoise: "${nameOfCentury_slowButSure(yearOrdinal)}"` ); return; } } console.log(`Checked ${endYearOrdinal + 1 - startYearOrdinal} years, all seems good`); })(); /*--> Checked 100000 years, all seems good 
[1, 99, 100, 101, 200, 300, 400, 1000, 1100, 1200, 1300, 1400, 1900, 2000, 2001, 2020, 10000, 10100].forEach(year => { console.log(`Year ${year} --> ${nameOfCentury(year)}`); }); /*--> Year 1 --> 1st Year 99 --> 1st Year 100 --> 1st Year 101 --> 2nd Year 200 --> 2nd Year 300 --> 3rd Year 400 --> 4th Year 1000 --> 10th Year 1100 --> 11th Year 1200 --> 12th Year 1300 --> 13th Year 1400 --> 14th Year 1900 --> 19th Year 2000 --> 20th Year 2001 --> 21st Year 2020 --> 21st Year 10000 --> 100th Year 10100 --> 101st 
Collapse
 
peter279k profile image
peter279k

Here is my simple solution with Python:

def what_century(year): year = str(year) pre_two_number = int(year[0] + year[1]) if year == '2000': return '20th' if year[2] != '0': pre_two_number += 1 if year[2] == '0' and year[3] == '0': pre_two_number += 0 if year[2] == '0' and year[3] != '0': pre_two_number += 1 pre_two_number = str(pre_two_number) if pre_two_number[1] == '1' and pre_two_number[0] != '1': pre_two_number += "st" elif pre_two_number[1] == '2' and pre_two_number[0] != '1': pre_two_number += "nd" elif pre_two_number[1] == '3' and pre_two_number[0] != '1': pre_two_number += "rd" else: pre_two_number += "th" return pre_two_number 
Enter fullscreen mode Exit fullscreen mode
Collapse
 
3limin4t0r profile image
3limin4t0r • Edited

This might be a bit over-engineered, but here is another Ruby solution:

def to_century(year) (year.to_i / 100 + 1).english.ordinal end class Integer def english English::Integer.new(self) end end module English class Integer def initialize(integer) @value = integer end ## # Returns ordinal notation of the current integer ("-2nd", "1st", "312th"). def ordinal "#{@value}#{ordinal_suffix}" end ## # Returns the ordinal suffix of the current integer ("st", "nd", "rd", "th"). def ordinal_suffix case @value.abs % 100 when 1, 21, 31, 41, 51, 61, 71, 81, 91 then 'st' when 2, 22, 32, 42, 52, 62, 72, 82, 92 then 'nd' when 3, 23, 33, 43, 53, 63, 73, 83, 93 then 'rd' else 'th' end end end end 
Enter fullscreen mode Exit fullscreen mode

Which produces the following output:

years = %w[8120 30200 1601 2020 3030 1900 1776] years.to_h { |year| [year, to_century(year)] } #=> {"8120"=>"82nd", "30200"=>"303rd", "1601"=>"17th", "2020"=>"21st", "3030"=>"31st", "1900"=>"20th", "1776"=>"18th"} 
Enter fullscreen mode Exit fullscreen mode
Collapse
 
thepeoplesbourgeois profile image
Josh • Edited
defmodule Year do @doc """ Returns the stringified, suffixed form of a numeric year. Use `to_century/1` if you need to do further numeric work on the century number before (or in lieu of) using it as a string. ## Examples iex> Year.centurify(8120) "82nd" iex> Year.centurify(30200) "303rd" iex> Year.centurify(1601) "17th" iex> Year.centurify(2020) "21st" iex> Year.centurify(3030) "31st" iex> Year.centurify(1900) "20th" iex> Year.centurify(1776) "18th" """ def centurify(year) do century = to_century(year) "#{century}#{suffix(century)}" end def to_century(year), do: div(year, 100) + 1 defp suffix(number) when number >= 100, do: number |> rem(100) |> suffix defp suffix(number) when number in 11..13, do: "th" defp suffix(number) do case rem(number, 10) do 1 -> "st" 2 -> "nd" 3 -> "rd" _ -> "th" end end end defmodule YearTest do import ExUnit.Case doctest Year end 
Enter fullscreen mode Exit fullscreen mode
Collapse
 
matrossuch profile image
Mat-R-Such

Py <3

def what_century(year): c, r = divmod(year,100) if r > 0: c += 1 #name  if c in [11,12,13]: return str(c)+'th' elif str(c)[-1] == '1': return str(c)+'st' elif str(c)[-1] == '2': return str(c) + 'nd' elif str(c)[-1] == '3': return str(c) + 'rd' else: return str(c) + 'th' 
Enter fullscreen mode Exit fullscreen mode
Collapse
 
mellen profile image
Matt Ellen-Tsivintzeli
function thuffix(n) { let ending = 'th'; if(n%100 != 11 && n%100 != 12 && n%100 != 13) { if(n%10 == 1) { ending = 'st'; } else if(n%10 == 2) { ending = 'nd'; } else if(n%10 == 3) { ending = 'rd'; } } return ending; } function getCentury(year) { let c = Math.floor(year/100); if(year%100 != 0) { c++; } return `${c}${thuffix(c)}`; }