DEV Community

Daily Challenge #110 - Love VS. Friendship

dev.to staff on November 07, 2019

If a = 1, b = 2, c = 3 ... z = 26 Then l + o + v + e = 54 and f + r + i + e + n + d + s + h + i + p = 108 So friendship is twice as strong as lo...
Collapse
 
ynndvn profile image
La blatte

A bit like @nicolas Hervé, using the reduce method:

f=a=>[...a].reduce((t,l)=>t+l.charCodeAt``-96,0)
  • [...a] transforms the string to an array with every character (["l", "o", "v", "e"])
  • The reduce methods will loop through every character, get its charCode, subtract 96 to it (the charCode associated with "a" + 1), and sum everything
Collapse
 
dak425 profile image
Donald Feury • Edited

I started picking up ruby for rails, so here is my shining gem.

Try it out here

word.rb

class Word
  @@alphabet = ('a'..'z').to_a

  def self.to_mark(word)
    word.chars.sum { |char| @@alphabet.index(char.downcase) + 1 }
  end
end

word_test.rb

require 'minitest/autorun'
require_relative 'word'

class TestWord < Minitest::Test
  def setup
    @cases = [
      { input: 'love', expected: 54 },
      { input: 'friendship', expected: 108 },
      { input: 'attitude', expected: 100 },
      { input: 'friends', expected: 75 },
      { input: 'family', expected: 66 },
      { input: 'selflessness', expected: 154 },
      { input: 'knowledge', expected: 96 }
    ]
  end

  def test_to_mark
    @cases.each { |test| assert_equal test[:expected], Word.to_mark(test[:input]) }
  end
end
Collapse
 
kesprit profile image
kesprit

Thanks to @ynndvn for showing me reduce method, it exist too in Swift language and it's awesome !!!

This is my solution in Swift :

func wordsToMarks(word: String) -> Int {
    return word.compactMap { $0 }.reduce(0) {
       $0 + Int($1.asciiValue ?? 0) - 96
    }
}

wordsToMarks(word:"attitude")
wordsToMarks(word:"friends")
wordsToMarks(word:"family")
wordsToMarks(word:"selflessness")
wordsToMarks(word:"knowledge")
Collapse
 
yechielk profile image
Yechiel Kalmenson
def wordsToMarks(word)
  alphabet = ("a".."z").to_a
  mark = 0
  word.each_char do |char|
    mark += alphabet.index(char.downcase) + 1
  end
  mark
end
Collapse
 
scrabill profile image
Shannon Crabill

("a".."z").to_a is nifty!

Collapse
 
yechielk profile image
Yechiel Kalmenson

Well, my first attempt had me iterating calling .index on ("a".."z") only to find out that you can't call index on a range, so in trying to work around that I realized I could just convert the range into an array... :)

Collapse
 
jbristow profile image
Jon Bristow
words_to_marks("",0).
words_to_marks(S,Mark) :-
    string_codes(S,SC),
    length(SC, SCL),
    sum_list(SC,SCS),
    Mark is SCS - SCL * 96.
?- words_to_marks(“love”, V).
% V = 54

?- words_to_marks(“declarative”, V).
% V = 100
Collapse
 
peter279k profile image
peter279k

Here is the simple solution with Python:

def words_to_marks(s):
    alphabet = {
        'a': 1,
        'b': 2,
        'c': 3,
        'd': 4,
        'e': 5,
        'f': 6,
        'g': 7,
        'h': 8,
        'i': 9,
        'j': 10,
        'k': 11,
        'l': 12,
        'm': 13,
        'n': 14,
        'o': 15,
        'p': 16,
        'q': 17,
        'r': 18,
        's': 19,
        't': 20,
        'u': 21,
        'v': 22,
        'w': 23,
        'x': 24,
        'y': 25,
        'z': 26,
    }

    sum_length = 0
    for char in s:
        sum_length += alphabet[char]

    return sum_length
Collapse
 
hnicolas profile image
Nicolas Hervé
const wordsToMarks = (word) => word.split("").reduce((acc, curr) => acc + curr.charCodeAt(0) - "a".charCodeAt(0) + 1, 0);
Collapse
 
khenhey profile image
Karin

A little solution for Ruby :) this was fun!

def wordsToMarks(word)
  strength = 0
  alphabet = ('a'..'z').to_a
  word.split('').each do |i|
    strength = strength + (alphabet.index(i) + 1)
  end
  return strength
end
Collapse
 
edreeseg profile image
Ed Reeseg • Edited
#include <stdio.h>

int main(int argc, char *argv[]) 
{
    if (argc != 2)
    {
        printf("Usage: ./strength string\n");
        return 1;
    }
    int sum = 0;
    char *c = argv[1];
    while(*c != '\0')
    {
        if (*c < 'a' || *c > 'z')
        {
            printf("Invalid argument\n");
            return 1;
        }
        sum += *c - 'a' + 1;
        c++;
    }
    printf("%i\n", sum);
    return 0;
}
Collapse
 
kesprit profile image
kesprit

Oh nice! That's better !

I forgot String are a table of Character so you right compactMap is useless.
I have totally ignored emojis because the challenger treat only letter a to z

So thank you for your feedback, your optimisation is truly better 👌

Collapse
 
tblanshard profile image
Tallie

My solution to the challenge using map and reduce in Python. If anyone has any suggestions on how to improve it, I would love to hear! :)

from functools import reduce 
def wordsToMarks(word):
    print(reduce((lambda x,y: x+y), map((lambda x: ord(x) - 96), list(word))))
Collapse
 
lloricode profile image
Lloric Mayuga Garcia • Edited

In PHP


$alpha = function (string $string) {
    $al = array_flip(range('a', 'z'));

    $points = 0;
    foreach (str_split($string) as $s) {
        $points += $al[$s] + 1;
    }
    return $points;
};

echo $alpha('friendship');

EDIT:

array_map(function (string $string) {
    $al = array_flip(range('a', 'z'));

    $points = 0;
    foreach (str_split($string) as $s) {
        $points += $al[$s] + 1;
    }
    echo "$string: $points<br>";
}, ['attitude', 'friends', 'family', 'selflessness', 'knowledge']);

attitude: 100
friends: 75
family: 66
selflessness: 154
knowledge: 96
Collapse
 
aminnairi profile image
Amin

Haskell

import Data.Char (ord)

wordsToMarks :: String -> Int
wordsToMarks = sum . map ((flip (-) 96) . ord)

Playground

Here.

Collapse
 
konvio profile image
Vitaliy Kononenko

Here is my fun solution using Kotlin:

fun wordsToMarks(word: String) = word.toCharArray()
        .map { it + 1 - 'a' }
        .sum()
Collapse
 
dak425 profile image
Donald Feury

Ah okay gotcha, thank ya for the tip!

Collapse
 
peledzohar profile image
Zohar Peled

c#, one liner using linq, ignoring non-letters chars:

int WordsToMarks(string word)
{
    return word.Where(c => char.IsLetter(c)).Sum(c => char.ToUpperInvariant(c) - 64);
}
Collapse
 
herobank110 profile image
David Kanekanian • Edited

My Python Algorithm:

words_to_marks = lambda words: sum(
    map(ord, words.lower()),
    -96 * len(words))
Collapse
 
aminnairi profile image
Amin

Thanks for your insight. I didn't know about subtract and when the second solution is kind of obscure to me it seems very cool and short.