loading...

Daily Challenge #260 - Subtract the Sum

thepracticaldev profile image dev.to staff ・2 min read

Complete the function which get an input number n such that n >= 10 and n < 10000, then:

Sum all the digits of n.
Subtract the sum from n, and it is your new n.
If the new n is in the list below return the associated fruit, otherwise return back to task 1.

Example
n = 325
sum = 3+2+5 = 10
n = 325-10 = 315 (not in the list)
sum = 3+1+5 = 9
n = 315-9 = 306 (not in the list)
sum = 3+0+6 = 9
n =306-9 = 297 (not in the list)
...
. ...until you find the first n in the list below.

Here are all possible values of n:

1-kiwi
2-pear
3-kiwi
4-banana
5-melon
6-banana
7-melon
8-pineapple
9-apple
10-pineapple
11-cucumber
12-pineapple
13-cucumber
14-orange
15-grape
16-orange
17-grape
18-apple
19-grape
20-cherry
21-pear
22-cherry
23-pear
24-kiwi
25-banana
26-kiwi
27-apple
28-melon
29-banana
30-melon
31-pineapple
32-melon
33-pineapple
34-cucumber
35-orange
36-apple
37-orange
38-grape
39-orange
40-grape
41-cherry
42-pear
43-cherry
44-pear
45-apple
46-pear
47-kiwi
48-banana
49-kiwi
50-banana
51-melon
52-pineapple
53-melon
54-apple
55-cucumber
56-pineapple
57-cucumber
58-orange
59-cucumber
60-orange
61-grape
62-cherry
63-apple
64-cherry
65-pear
66-cherry
67-pear
68-kiwi
69-pear
70-kiwi
71-banana
72-apple
73-banana
74-melon
75-pineapple
76-melon
77-pineapple
78-cucumber
79-pineapple
80-cucumber
81-apple
82-grape
83-orange
84-grape
85-cherry
86-grape
87-cherry
88-pear
89-cherry
90-apple
91-kiwi
92-banana
93-kiwi
94-banana
95-melon
96-banana
97-melon
98-pineapple
99-apple
100-pineapple

Tests:
SubtractSum(10)
SubtractSum(1204)

Good luck!


This challenge comes from aryan-firouzian 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!

Discussion

pic
Editor guide
Collapse
peter279k profile image
peter279k

Here is my simple solution to find the fruit name with PHP:

function subtractSum($n) {
  // fruit name "apple"
  $fruitArray = ["kiwi",
"pear",
"kiwi",
"banana",
"melon",
"banana",
"melon",
"pineapple",
"apple",
"pineapple",
"cucumber",
"pineapple",
"cucumber",
"orange",
"grape",
"orange",
"grape",
"apple",
"grape",
"cherry",
"pear",
"cherry",
"pear",
"kiwi",
"banana",
"kiwi",
"apple",
"melon",
"banana",
"melon",
"pineapple",
"melon",
"pineapple",
"cucumber",
"orange",
"apple",
"orange",
"grape",
"orange",
"grape",
"cherry",
"pear",
"cherry",
"pear",
"apple",
"pear",
"kiwi",
"banana",
"kiwi",
"banana",
"melon",
"pineapple",
"melon",
"apple",
"cucumber",
"pineapple",
"cucumber",
"orange",
"cucumber",
"orange",
"grape",
"cherry",
"apple",
"cherry",
"pear",
"cherry",
"pear",
"kiwi",
"pear",
"kiwi",
"banana",
"apple",
"banana",
"melon",
"pineapple",
"melon",
"pineapple",
"cucumber",
"pineapple",
"cucumber",
"apple",
"grape",
"orange",
"grape",
"cherry",
"grape",
"cherry",
"pear",
"cherry",
"apple",
"kiwi",
"banana",
"kiwi",
"banana",
"melon",
"banana",
"melon",
"pineapple",
"apple",
"pineapple",];

  $number = $n;
  while(true) {
      $str = (string)$number;
      $sum = 0;
      for($index=0; $index<strlen($str); $index++) {
          $sum += (int)$str[$index];
      }

      $number = $number - $sum;

      if ($number <= 99) {
          break;
      }

  }

  return  $fruitArray[$number-1];
}
Collapse
__victorchan profile image
Victor Chan

Heres my solution in Javascript:
It seems like it always returns apple, pretty neat question huh (Unless im wrong? 😅)

const SubtractSum = return () => "apple"

How I found this out:

const fruits = [
"kiwi",
  "pear",
  "kiwi",
  "banana",
...
 "melon",
  "pineapple",
  "apple",
  "pineapple",
]

const SubtractSum = x => {
  const sum = `${x}`.split("").reduce((p, c) => +p + +c, 0)
  const y = x - sum
  return y <= 99 ? fruits[y - 1] : SubtractSum(y)
}

//Testing out all possible combinations 10 -- 10000
for (let i = 10; i < 10000; i++) {
  console.log(i, SubtractSum(i)) //Prints "apple"
} 

Collapse
pbouillon profile image
Pierre Bouillon

My version, in C# 😄

    public static string GetMatchingWordFor(int number)
    {
        var nValues = GetDictionaryFromRawString(RawValues);

        while (!nValues.ContainsKey(number))
        {
            number -= number.ToString()
                .Select(digit => int.Parse(digit.ToString()))
                .Aggregate(0, (acc, x) => acc + x);
        }

        return nValues[number];
    }

The helper function to convert the raw list into a usable dictionary:

    public static Dictionary<int, string> GetDictionaryFromRawString(string raw)
    {
        return raw.Split("\n")
            .Select(str =>
                str.Trim()
                    .Split("-"))
            .ToDictionary(
                row => int.Parse(row[0]),
                row => row[1]);
    }
Collapse
alxtrnr profile image
Alex Turner

I think this might be called a naive solution...

import random

def number_fruit():
    fruit_list = []
    fruit_dict = {
        1:'kiwi',
        2:'pear',
        3:'kiwi',
        4:'banana',
        5:'melon',
        6:'banana',
        7:'melon',
        8:'pineapple',
        9:'apple',
        10:'pineapple',
        11:'cucumber',
        12:'pineapple',
        13:'cucumber',
        14:'orange',
        15:'grape',
        16:'orange',
        17:'grape',
        18:'apple',
        19:'grape',
        20:'cherry',
        21:'pear',
        22:'cherry',
        23:'pear',
        24:'kiwi',
        25:'banana',
        26:'kiwi',
        27:'apple',
        28:'melon',
        29:'banana',
        30:'melon',
        31:'pineapple',
        32:'melon',
        33:'pineapple',
        34:'cucumber',
        35:'orange',
        36:'apple',
        37:'orange',
        38:'grape',
        39:'orange',
        40:'grape',
        41:'cherry',
        42:'pear',
        43:'cherry',
        44:'pear',
        45:'apple',
        46:'pear',
        47:'kiwi',
        48:'banana',
        49:'kiwi',
        50:'banana',
        51:'melon',
        52:'pineapple',
        53:'melon',
        54:'apple',
        55:'cucumber',
        56:'pineapple',
        57:'cucumber',
        58:'orange',
        59:'cucumber',
        60:'orange',
        61:'grape',
        62:'cherry',
        63:'apple',
        64:'cherry',
        65:'pear',
        66:'cherry',
        67:'pear',
        68:'kiwi',
        69:'pear',
        70:'kiwi',
        71:'banana',
        72:'apple',
        73:'banana',
        74:'melon',
        75:'pineapple',
        76:'melon',
        77:'pineapple',
        78:'cucumber',
        79:'pineapple',
        80:'cucumber',
        81:'apple',
        82:'grape',
        83:'orange',
        84:'grape',
        85:'cherry',
        86:'grape',
        87:'cherry',
        88:'pear',
        89:'cherry',
        90:'apple',
        91:'kiwi',
        92:'banana',
        93:'kiwi',
        94:'banana',
        95:'melon',
        96:'banana',
        97:'melon',
        98:'pineapple',
        99:'apple',
        100:'pineapple'        
    }

    num_int = random.randint(10,10000)
    num_str = str(num_int)
    num_list = list(num_str)    
    num_list_int = []


    for x in num_list:
        xint = int(x)
        num_list_int.append(xint)

    sum_num_int_list = sum(num_list_int)   
    new_n = num_int - sum_num_int_list

    if new_n in fruit_dict:
        print(new_n,'=',fruit_dict[new_n])
    else: 
        number_fruit()

number_fruit()

...and neither do I understand recursion (maximum recursion depth exceeded while calling a Python object) and why it always comes up apple.

Collapse
mistrikushal profile image
Kushal

Here is Ruby solution,

FRUITS = {
  1 => 'kiwi',
   ...
  100 => 'pineapple'
}

def substract_sum(num)
  if num >= 10 && num < 10000
    sum_of_digits = num.to_s.chars.map(&:to_i).inject(:+)
    if FRUITS.keys.include?(sum_of_digits)
      puts FRUITS[sum_of_digits]
    else
      puts "#{sum_of_digits} (not in the list)"  
    end
  else
    puts 'Enter valid number'  
  end
end

substract_sum(10)
substract_sum(1204)
Collapse
lxxxvi profile image
Mario

Yanother Ruby solution

FRUIT = {
  '1' => 'kiwi',
# ...
  '100' => 'pineapple'
}

def subtract_sum(number)
  return unless (10...10_000).cover?(number)

  loop do
    number_split = number.to_s.split('')
    to_subtract = number_split.reduce(0) { |sum, i| sum += i.to_i }
    number -= to_subtract

    return FRUIT[number.to_s] if FRUIT.key?(number.to_s)
  end
end
Collapse
boris profile image
Boris Quiroz

Some python-that-can-be-improved:

elements = [
        "1-kiwi",
        "2-pear",
        "3-kiwi",
        "4-banana",
        "5-melon",
        "6-banana",
        "7-melon",
        "8-pineapple",
        "9-apple",
        "10-pineapple",
        "...",
        "100-pineapple"
        ]

def substractSum(n):
    if 10 <= n <= 10000:
        sum_n = 0
        for digit in str(n):
            sum_n += int(digit)

        result = n - sum_n

        while result > 100:
            for digit in str(n):
                sum_n += int(digit)
            result = n - sum_n

        print(n, result, elements[result-1])
    else:
        print("{}: Use value between 10 and 10000".format(n))

substractSum(9)
substractSum(10)
substractSum(31)
substractSum(110)
substractSum(111)
substractSum(325)
substractSum(1204)
substractSum(1316)
substractSum(2888)
substractSum(10000)
substractSum(10001)

Output of the above:

❯ python 260.py
9: Use value between 10 and 10000
10 9 9-apple
31 27 27-apple
110 100 100-pineapple
111 99 99-apple
325 95 95-melon
1204 98 98-pineapple
1316 95 95-melon
2888 80 80-cucumber
10000 100 100-pineapple
10001: Use value between 10 and 10000
Collapse
pinotattari profile image
Riccardo Bernardini

Ada solution

with Ada.Strings.Unbounded;              use Ada.Strings.Unbounded;

subtype Parameter_Type is Integer range 10 .. 9999; 

subtype Fruit_Index is Integer range 1 .. 100;

Names : array(Fruit_Index) of Unbounded_String  := 
    ( 
-- Fill with names
     );

function SubctractSum(N : Parameter_Type)  return Unbounded_String
is (if N in Fruit_Index then Names(N) else "apple");

-- Explanation: 
-- N can be written as 
--
--       N = a*1000 + b*100 + c*10 + d 
--
-- if N <= 100, we access directly the name array.  
--
-- If N > 100 (which means b >= 1) the new N is
--
--       New_N = a*1000 + b*100 + c*10 + d - (a+b+c+d)
--                     = a*999 + b*99 + c*9
--
-- If the iteration stops with New_N it must be 
--  New_N <= 100 which implies a = 0,  b=1 
-- (it cannot be b=0 otherwise we would had 
-- not done another iteration) and c=0, that is,  
-- New_N = 99.
--
-- Therefore, unless N<=100, the result is "apple"
Collapse
vidit1999 profile image
Vidit Sarkar

Here is a solution,

return "apple";
Collapse
vidit1999 profile image
Vidit Sarkar

And here is a recursive Python solution,

fruits = [
    "kiwi",
    "pear",
    ....
    "melon",
    "pineapple",
    "apple",
    "pineapple"
]

def SubtractSum(number : int) -> str:
    temp = number - sum(map(int ,str(number)))
    if(1 <= temp <= 100):
        return fruits[temp-1]
    return SubtractSum(temp)
Collapse
lexlohr profile image
Alex Lohr

Rust solution:

const FRUITS: [&'static str; 100] = [
    "kiwi",
    "pear",
    "kiwi",
    "banana",
    "melon",
    "banana",
    "melon",
    "pineapple",
    "apple",
    "pineapple",
    "cucumber",
    "pineapple",
    "cucumber",
    "orange",
    "grape",
    "orange",
    "grape",
    "apple",
    "grape",
    "cherry",
    "pear",
    "cherry",
    "pear",
    "kiwi",
    "banana",
    "kiwi",
    "apple",
    "melon",
    "banana",
    "melon",
    "pineapple",
    "melon",
    "pineapple",
    "cucumber",
    "orange",
    "apple",
    "orange",
    "grape",
    "orange",
    "grape",
    "cherry",
    "pear",
    "cherry",
    "pear",
    "apple",
    "pear",
    "kiwi",
    "banana",
    "kiwi",
    "banana",
    "melon",
    "pineapple",
    "melon",
    "apple",
    "cucumber",
    "pineapple",
    "cucumber",
    "orange",
    "cucumber",
    "orange",
    "grape",
    "cherry",
    "apple",
    "cherry",
    "pear",
    "cherry",
    "pear",
    "kiwi",
    "pear",
    "kiwi",
    "banana",
    "apple",
    "banana",
    "melon",
    "pineapple",
    "melon",
    "pineapple",
    "cucumber",
    "pineapple",
    "cucumber",
    "apple",
    "grape",
    "orange",
    "grape",
    "cherry",
    "grape",
    "cherry",
    "pear",
    "cherry",
    "apple",
    "kiwi",
    "banana",
    "kiwi",
    "banana",
    "melon",
    "banana",
    "melon",
    "pineapple",
    "apple",
    "pineapple",
];

fn subtract_sum(sum: i32) -> &'static str {
    let mut s = sum;
    *FRUITS
        .iter()
        .nth(loop {
            if s <= 100 {
                break (s - 1) as usize;
            }
            s -= s
                .to_string()
                .chars()
                .map(|c| (c as u8 - 48) as i32)
                .sum::<i32>();
        })
        .unwrap()
}
Collapse
willsmart profile image
willsmart

A quick JS one:

First up, set up the base fruit mapping by splitting that string:

const
  inputFruitMappingString = `1-kiwi
2-pear
...other entries...
99-apple
100-pineapple`,
  baseFruitMapping = Object.fromEntries(
    inputFruitMappingString.split('\n').map(line => line.split('-'))
  )

The fruit-fetching-function itself:

function fruitForIndex(i) {
  return baseFruitMapping[i] ??
    fruitForIndex(
      [...String(i)].reduce((acc, digit) => acc - digit, i)
    );
}

The guts of that is: [...String(i)].reduce((acc, digit) => acc - digit, i)
Breaking that up:

  • String(i): i is a number so to split it into characters, render it into a standard decimal string
  • [...String(i)]: Easy way to split the string into chars
  • [...String(i)].reduce((acc, digit) => acc - digit, i): The reduce function is passed the number itself as its initial value and then goes through the array of digits, subtracting each from the running total.

Bit of sanity checking...

// Debug version of the function
function fruitForIndex(i) {
  console.log(i), 
  return baseFruitMapping[i] ?? fruitForIndex([...String(i)].reduce((acc, digit) => acc - digit, i));
}

> fruitForIndex(1)
1
< "kiwi"

> fruitForIndex(100)
100
< "pineapple"

> fruitForIndex(101)
101
99
< "apple"

> fruitForIndex(200)
200
198
180
171
162
153
144
135
126
117
108
99
< "apple"


Note that it's worth making sure you have a modern JS engine
Caniuse for Object.fromEntries
Caniuse for ??

Collapse
jurerotar profile image
Jure Rotar

Simple PHP solution using array_reduce

function substractTheSum(int $number): string {
    $fruitList = [
        1 => 'kiwi',
        2 => 'pear',
        // ...
    ];
    while($number > 100) {
        $number -= array_reduce(str_split((string) $number), fn($carry, string $num) => $carry += (int) $num);
    }
    return $fruitList[$number];
}
Collapse
aminnairi profile image
Amin

Go

EDIT: just realized this challenge was a trap, but leaving the (wrong) solution here for people wanting to try out Go (it's awesome, try it).

Commands for initializing the project.

$ mkdir $GOPATH/src/fruits
$ cd $GOPATH/src/fruits
$ touch fruits.go

The source-code.

// Set of utilities for manipulating fruits.
package fruits

// Find a fruit based on its index.
func FindFromInteger(integer uint16) string {
    if integer < 9 {
        switch (integer) {
        case 1:
            return "kiwi"

        case 2:
            return "pear"

        case 3:
            return "kiwi"

        case 4:
            return "banana"

        case 5:
            return "melon"

        case 6:
            return "banana"

        case 7:
            return "melon"

        case 8:
            return "pineapple"
        }
    }

    return "apple"
}

Commands for the unit tests.

$ touch fruits_test.go

The source-code for unit tests.

package fruits_test

import "testing"
import "fruits"
import "fmt"

func TestFindFromInteger(t *testing.T) {
    var valuesExpectations map[uint16]string = map[uint16]string{
        0: "apple",
        1: "kiwi",
        2: "pear",
        3: "kiwi",
        4: "banana",
        5: "melon",
        6: "banana",
        7: "melon",
        8: "pineapple",
        9: "apple",
        10: "apple",
        100: "apple",
        1_000: "apple",
        325: "apple",
        10_000: "apple",
    }

    for value, expectation := range valuesExpectations {
        var result string = fruits.FindFromInteger(value)

        if result != expectation {
            t.Errorf("Expected fruits.FindFromInteger(%d) to equal %s but got %s.", value, expectation, result)
        }
    }
}

func BenchmarkFindFromInteger(b *testing.B) {
    for index := 0; index < b.N; index++ {
        fruits.FindFromInteger(10_000)
    }
}

func ExampleFindFromInteger() {
    fmt.Printf("Fruit for index %d is %q.\n", 15, "apple")
    // Output: Fruit for index 15 is "apple".
}

Commands for the tests, benchmark and coverage.

$ go test -cover -bench .
goos: linux
goarch: amd64
pkg: fruits
BenchmarkFindFromInteger-4      482598516                2.58 ns/op
PASS
coverage: 100.0% of statements
ok      fruits  1.500s
Collapse
saswat01 profile image
saswat

Python grill:

alt code

Collapse
loriick profile image
Travailleur Lorick

why I always get apple 😅 ?

Collapse
pinotattari profile image
Riccardo Bernardini

Sum all the digits of n.

Base ten is implicit, I suppose.