dev.to staff

Posted on

# Daily Challenge #71 - See you next Happy Year

You're saying goodbye to your friend when they say to you, "See you next happy year!" You smile and wave, saying you'll see them then. But wait, when's the next happy year anyway?

Given a year, write a function that will return the closest year you'll see your friend, the next year with all unique digits.

Years will always be represented as positive integers. It is not necessary for the year passed through the function to be a Happy one.

Examples:
`nextHappyYear(7712) ==> 7801`
`nextHappyYear(1001) ==> 1023`
`nextHappyYear(2018) ==> 2019`

This challenge by MrZizoScream on CodeWars was used for inspiration. 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!

Javascript:

``````function nextHappyYear(year) {
const nextYear = ~~year + 1;
const isHappyYear = new Set(`\${nextYear}`).size === `\${year}`.length;
if (!isHappyYear) {
return nextHappyYear(nextYear);
}

return nextYear;
}
``````

Results:

``````nextHappyYear(2018);
// 2019
nextHappyYear(1001);
// 1023
nextHappyYear(7712);
// 7801
``````

Zohar Peled

Clever usage of Set!

Oleksii Filonenko • Edited

Elixir (now with doctests!):

``````defmodule Day71 do
@doc """
Finds the next happy year after `year`.

iex> Day71.next_happy_year(7712)
7801
iex> Day71.next_happy_year(1001)
1023
iex> Day71.next_happy_year(2018)
2019
"""
@spec next_happy_year(pos_integer) :: pos_integer
def next_happy_year(year) do
(year + 1)
|> Stream.iterate(&(&1 + 1))
|> Enum.find(&happy?/1)
end

@doc """
Checks if a year is a happy year.

A year is happy if all its digits are unique.

iex> Day71.happy?(2019)
true
iex> Day71.happy?(2021)
false
"""
@spec happy?(pos_integer) :: boolean
def happy?(year) do
digits = Integer.digits(year)
Enum.uniq(digits) == digits
end
end
``````

And a test file (just for the sake of completeness):

``````defmodule Day71Test do
use ExUnit.Case
doctest Day71
end
``````

E. Choroba

Using a regex in Perl:

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

sub next_happy_year {
my (\$year) = @_;
1 while ++\$year =~ /(.).*\1/;
\$year
}

use Test::More tests => 3;

is next_happy_year(7712) => 7801;
is next_happy_year(1001) => 1023;
is next_happy_year(2018) => 2019;
``````

Amin • Edited

Elm

``````module NextHappyYear exposing (nextHappyYear)

import List exposing (length)
import String exposing (any, fromChar, fromInt, indexes)

isMultiple : List anything -> Bool
isMultiple list =
length list > 1

nonUniqueCharacterIn : String -> Char -> Bool
nonUniqueCharacterIn string character =
indexes (fromChar character) string
|> isMultiple

nextHappyYear : Int -> Int
nextHappyYear year =
let
nextYear : Int
nextYear =
year + 1

yearString : String
yearString =
nextYear
|> fromInt

nonHappyYear : Bool
nonHappyYear =
yearString
|> any (nonUniqueCharacterIn yearString)
in
if nonHappyYear then
nextHappyYear nextYear

else
nextYear
``````

Tests

``````module NextHappyYearTest exposing (suite)

import Expect exposing (equal)
import NextHappyYear exposing (nextHappyYear)
import Test exposing (Test, describe, test)

suite : Test
suite =
describe "Next happy year"
[ test "It should return 7712 when passing 7801" <|
\_ ->
equal 7801 <| nextHappyYear 7712
, test "It should return 1001 when passing 1023" <|
\_ ->
equal 1023 <| nextHappyYear 1001
, test "It should return 2019 when passing 2018" <|
\_ ->
equal 2019 <| nextHappyYear 2018
]
``````

Edit

Just realized there is a native Set module in Elm by looking at the comments made in JavaScript which is awesome, but I'll keep this as is for the record. I'm edgy anyway!

Edit2

Turns out, after an interesting talk with the folks at the Elm Slack, and some experimentations, there is no way to to `Set` that keeps the order of the `List` due to the Haskell implementation behind, preventing to have an easy solution. So this means either use an extra library (which I tend to avoid since I wanted to show a native Elm solution) or use a combination just like I did!

Anwar

Here is my solution using PHP:

``````if (!function_exists("hasUniqueDigits")) {
function hasUniqueDigits(int \$number): bool {
\$digits = str_split(\$number);

return \$digits === array_unique(\$digits);
}
}

if (!function_exists("nextHappyYear")) {
function nextHappyYear(int \$year): int {
\$nextYear = \$year + 1;

while(!hasUniqueDigits(\$nextYear)) {
\$nextYear++;
}

return \$nextYear;
}
}
``````

And here is my unit tests:

``````use PHPUnit\Framework\TestCase;

class NextHappyYearTest extends TestCase {
public function testShouldReturnNextHappyYear() {
\$this->assertEquals(nextHappyYear(7712), 7801);
}

public function testShouldReturnOtherNextHappyYear() {
\$this->assertEquals(nextHappyYear(1001), 1023);
}

public function testShouldReturnOtherOtherNextHappyYear() {
\$this->assertEquals(nextHappyYear(2018), 2019);
}
}
``````

Hope you like it :)

Oleksii Filonenko

Rust:

``````fn next_happy_year(year: u32) -> u32 {
let mut year = year + 1;
while !happy(year) {
year += 1;
}
year
}

fn happy(year: u32) -> bool {
let mut chars = year.to_string().chars().collect::<Vec<_>>();
chars.sort();
let len = chars.len();
chars.dedup();
chars.len() == len
}
``````

This was a strange exercise to do in Rust. Feels dirty to use conversion to string :(

Michael Baas • Edited

APL (I'm using Dyalog APL)

Code:

`{4=+/βdβββ΅:β΅βββ΅+1}`

Tests:

```     {4=+/βdβββ΅:β΅βββ΅+1}7712
7801
{4=+/βdβββ΅:β΅βββ΅+1}1001
1023
{4=+/βdβββ΅:β΅βββ΅+1}2019
2019
```

Vinnie

Simple JS solution:

``````function nextHappyYear(year){
let newYear = year + 1;
let arr = newYear.toString().split('');
let uniq = arr.filter((item, pos) => arr.indexOf(item) == pos);
if (uniq.length !== arr.length)
return nextHappyYear(newYear);
return newYear;
}
``````

Vinnie • Edited

And a PHP solution:

``````function nextHappyYear(\$year){
\$newYear = \$year+1;
return strlen(\$newYear) == count(array_unique(str_split(\$newYear))) ? \$newYear : nextHappyYear(\$newYear);
}
``````

dillan teagle

quick python solution

``````def nextHappyYear(year):
next_year = year + 1
yr_list = [int(x) for x in str(year)]
happy_year = len(set(yr_list)) == len(yr_list)
if not happy_year:
return nextHappyYear(next_year)

return happy_year
``````

My ugly answer. But I thought I would at least give this a go in python.

``````
def find_happy_year(string)
not_happy = True
while(not_happy):
for letter in string:
same_same = 0
for other_letter in string:
if letter == other_letter:
same_same += 1
if same_same > 1:
not_happy = True
string = str( int(string) + 1 )
break
else:
not_happy = False
print (string)
``````

Oleksii Filonenko

Great, thanks! I blanked out on this for some reason :)