# Daily Challenge #54 - What century is it?

### dev.to staff twitter logo Aug 31 '19・1 min read

Daily Challenge (159 Part Series)

Challenge
Write a function that will return an inputted numerical year in century format. The output should have the appropriate written ending ('st','nd','rd','th') as well.

Examples
In: `2259` Out: `23rd`
In: `1124` Out: `12th`
In: `2000` Out: `21st`

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!

DISCUSS (22) A reasonably short and reasonably Rusty solution:

``````pub fn century(year: u32) -> String {
let century = year / 100 + 1;
let suffix = match century % 100 {
11 | 12 | 13 => "th",
_ => match century % 10 {
1 => "st",
2 => "nd",
3 => "rd",
_ => "th",
},
};
format!("{}{}", century, suffix)
}
``````

F#:

``````module Century

let private parseYear s =
let n = int s
if n >= 0 then Ok n
else Error "Year must be >= 0"

let private suffix c =
match c % 100 with
| 11
| 12
| 13 -> "th"
| _ ->
match c % 10 with
| 1 -> "st"
| 2 -> "nd"
| 3 -> "rd"
| _ -> "th"

let century (year : string) =
match parseYear year with
| Ok year ->
let c = year / 100 + 1
sprintf "%d%s" c (suffix c)
| Error msg -> failwith msg
``````

Failing on inputs < 0 was an arbitrary decision, it's easy to adopt the current code to take care of BC/AD.

Tests:

``````module CenturyTest

open FsUnit.Xunit
open Xunit
open Century

[<Fact>]
let ``2259``() = century "2259" |> should equal "23rd"

[<Fact>]
let ``1124``() = century "1124" |> should equal "12th"

[<Fact>]
let ``2000``() = century "2000" |> should equal "21st"

[<Fact>]
let ``0``() = century "0" |> should equal "1st"

[<Fact>]
let ``111``() = century "111" |> should equal "2nd"

[<Fact>]
let ``2245``() = century "2245" |> should equal "23rd"

[<Fact>]
let ``invalid year``() = (fun () -> century "-1" |> ignore) |> shouldFail
``````

A bit of functional JS

``````const test = require('./tester');

const century = year => {
if (isNaN(year)) return null;
const nYear = Number(year);
const cent = Math.floor(nYear / 100) + 1;
const suffix = Math.floor(cent / 10) % 10 === 1 ? 'th'
: cent % 10 === 1 ? 'st'
: cent % 10 === 2 ? 'nd'
: cent % 10 === 3 ? 'rd'
: 'th';
return `\${cent}\${suffix}`;
}

test(century, [
{
in: ,
out: '23rd',
},
{
in: ,
out: '12th',
},
{
in: ,
out: '21st'
},
{
in: ,
out: '111th',
},
]);
``````

F#

``````let whatCenture (year: int) =
let centure = year / 100 + 1

let suffix x =
if (centure % 13) = 12  || (centure % 13) = 11
then "th"
else match x % 10 with
| 1 -> "st"
| 2 -> "nd"
| 3 -> "rd"
| _ -> "th"

(string centure) + (suffix centure)

``````

Always nice to see another F# solution :-)

Thanks

Yes, yes, I know, 2000 should return "21st" century. I don't know of anyone who counts centuries like that, so my function returns them according to normal use.

``````const addBC = year => year < 0 ? " BC" : ""

const centurify = year => {
const num = Math.ceil(Math.abs(year) / 100).toString()
const suffix = num.match(/(11|12|13)\$/)
? "th" : num.endsWith("1")
? "st" : num.endsWith("2")
? "nd" : num.endsWith("3")
? "rd" : "th"
return num + suffix + addBC(year)
}
``````

This would've been even more interesting using the strict usage of "century" ;-)

``````#!/usr/bin/perl
use warnings;
use strict;

sub century {
my (\$year) = @_;
my \$century = 1 + int(\$year / 100);
my \$suffix;
\$suffix = 'th' if grep \$century == \$_, 11 .. 13;
\$suffix ||= {
1 => 'st',
2 => 'nd',
3 => 'rd',
}->{ substr \$century, -1 } || 'th';
\$century . \$suffix
}

use Test::More tests => 6;
is century(33),    '1st';
is century(2259), '23rd';
is century(1124), '12th';
is century(2000), '21st';
is century(3199), '32nd';
is century(2423), '25th';
``````

First handle the exceptions (i.e. 11 - 13), then just use the last digit to decide.

A length Javascript solution, but I did not want to divide by 100.

``````const century = year => {
const yearString = year.toString();
const n = String(year).length;
if (n - 3 < 0) {
console.log("0th century");
} else {
console.log(digitYears(yearString, n));
}
};

const digitYears = (yearString, n) => {
const toIntAgain = parseInt(yearString[n - 3]) + 1;
const edges = parseInt(yearString.slice(n - 4, n - 2)) + 1;
if (edges == 11 || edges == 12 || edges == 13) {
return `\${yearString.slice(0, n - 3)}\${toIntAgain}th century`;
} else {
const ending = endingDetermine(toIntAgain);
return `\${yearString.slice(0, n - 3)}\${toIntAgain}\${ending} century`;
}
};

const endingDetermine = digit => {
let ending = "";
switch (digit) {
case 1:
ending = "st";
break;
case 2:
ending = "nd";
break;
case 3:
ending = "rd";
break;
default:
ending = "th";
break;
}
return ending;
};
``````

Tried it with a few different years including the edge cases.

``````century(11034); //111th century
century(15134); //152nd century
century(16234); //163th century
century(942); //10th century
century(2042); //21st century
century(1342); //14th century
century(1242); //13th century
century(52); //0th century
``````

Ah, this one was tricker than I thought because of the edge cases.

I choose a solution in JS that lists out all the endings in an object - but since they are almost all the same, maybe I should have done something else :)

Also, since I've started recording me solving these, you can check it out here: youtube.com/watch?v=ozws2mzhqkM

``````const centuryName = year => {
const endings = {
0: 'th',
1: 'st',
2: 'nd',
3: 'rd',
4: 'th',
5: 'th',
6: 'th',
7: 'th',
8: 'th',
9: 'th',
}

const century = Math.floor(year / 100) + 1
const rem = century % 10
const ending = [11, 12, 13].includes(century % 100)
? 'th' : endings[rem]
return `\${century}\${ending}`
}
``````

Insert Go Pun Here

century.go

``````package century

import (
"strconv"
)

// Century gives the text representation of what century the given date belongs to
func Century(date int) string {
// if date is negative (BC), convert to positive
if date < 0 {
date *= -1
}
prefix := date/100 + 1

var suffix string

// if its one the weird teens centuries, suffix is "th"
switch prefix % 100 {
case 11, 12, 13:
suffix = "th"
default:
switch prefix % 10 {
case 1:
suffix = "st"
case 2:
suffix = "nd"
case 3:
suffix = "rd"
default:
suffix = "th"
}
}

return strconv.Itoa(prefix) + suffix
}

``````

century_test.go

``````package century

import "testing"

func TestCentury(t *testing.T) {
testCases := []struct {
description string
input       int
expected    string
}{
{
"twenty third centry",
2259,
"23rd",
},
{
"twelfth century",
1124,
"12th",
},
{
"twenty first century",
2000,
"21st",
},
{
"small centry",
24,
"1st",
},
{
"odd centry name",
1013,
"11th",
},
{
"large odd century name",
11013,
"111th",
},
{
"negative century",
-2000,
"21st",
},
}

for _, test := range testCases {
if result := Century(test.input); result != test.expected {
t.Fatalf("FAIL: %s - Centry(%d): %s - expected '%s'", test.description, test.input, result, test.expected)
}
t.Logf("PASS: %s", test.description)
}
}

``````

Classic DEV Post from Jul 17 '19

## My 2019 Remote Office Tour 🚀

`DEV.join()`

Come for the ideas.
Stay for the community.  