r/dailyprogrammer • u/rya11111 3 1 • May 14 '12
[5/14/2012] Challenge #52 [easy]
Imagine each letter and its position within the alphabet. Now assign each letter its corresponding value ie a=1, b=2,... z=26. When given a list of words, order the words by the sum of the values of the letters in their names.
Example: Shoe and Hat
Hat: 8+1+20 = 29
Shoe: 19+8+15+5 = 47
So the order would be Hat, Shoe.
For extra points, divide by the sum by the number of letters in that word and then rank them.
thanks to SpontaneousHam for the challenge at /r/dailyprogrammer_ideas .. link
Please note that [difficult] challenge has been changed since it was already asked
http://www.reddit.com/r/dailyprogrammer/comments/tmnfn/5142012_challenge_52_difficult/
fortunately, someone informed it very early :)
3
u/jonzo1 May 14 '12
Clojure:
(defn int-value [c] (- (Character/digit c 36) 9)) (defn compute-sum [word] (->> word (map int-value) (reduce +))) (defn do-rank [& words] (sort-by compute-sum words))
3
u/ret0 May 14 '12
Python3:
def mytotal(word): return sum([ord(x)-96 for x in word.lower()]) def mysort(seq): return sorted(seq, key=mytotal)
→ More replies (3)
2
u/luxgladius May 14 '12
Perl
use List::Util qw/sum/;
use List::MoreUtils qw/zip/;
my @alph = 'a'..'z'; my @num = 1 .. 26;
my %map = zip(@alph, @num); my %val; my %avg;
while(<>) {
$_ = lc;
s/[^a-z]//g;
$val{$_} = sum(map {$map{$_}} grep /[a-z]/, split //, lc);
$avg{$_} = $val{$_} / length;
print "$val{$_}, $avg{$_}\n";
}
for my $rank (\%val, \%avg) {
print join(", ", sort {$rank->{$a} <=> $rank->{$b}} keys %$rank), "\n";
}Output
perl dp52e.pl hat 29, 9.66666666666667 shoe 47, 11.75 ^Z hat, shoe hat, shoe
2
u/loonybean May 14 '12 edited May 14 '12
Javascript:
function orderWords(words) //words is an array of strings
{
words.sort(function(a,b)
{
aScore = 0, bScore = 0, aLen = a.length, bLen = b.length;
a = a.toLowerCase(), b = b.toUpperCase();
for(var i=0;i<aLen || i<bLen;i++)
{
aScore += i < aLen ? a.charCodeAt(i) - 64 : 0;
bScore += i < bLen ? b.charCodeAt(i) - 64 : 0;
}
return aScore - bScore;
});
return words;
}The answer to the bonus question is hardly any different:
function orderWords(words) //words is an array of strings
{
words.sort(function(a,b)
{
aScore = 0, bScore = 0, aLen = a.length, bLen = b.length;
a = a.toLowerCase(), b = b.toUpperCase();
for(var i=0;i<aLen || i<bLen;i++)
{
aScore += i < aLen ? a.charCodeAt(i) - 64 : 0;
bScore += i < bLen ? b.charCodeAt(i) - 64 : 0;
}
return aScore/aLen - bScore/bLen;
});
return words;
}
→ More replies (4)
1
u/drb226 May 14 '12
ghci> :m +Data.List Data.Ord Data.Char ghci> let wordScore = sum . map ((subtract (ord 'a' - 1)) . ord . toLower) ghci> wordScore "Hat" 29 ghci> wordScore "Shoe" 47 ghci> let mySort = sortBy (comparing wordScore) ghci> mySort $ words "Hat Shoe" ["Hat", "Shoe"] ghci> let wordScore' str = fromIntegral (wordScore str) / fromIntegral (length str) ghci> let mySort' = sortBy (comparing wordScore')
1
May 14 '12
public static int wordValue(String word) {
int sum = 0;
word = word.toLowerCase();
for(int i = 0; i < word.length(); i++)
sum += word.charAt(i) - 'a' + 1;
return sum;
}
public static void QuickSortWords(int[] values, String[] words, int low, int high) {
int i = low, j = high;
int mid = values[(low + high) / 2];
while(i <= j) {
while(values[i] < mid) i++;
while(values[j] > mid) j--;
if(i < j) {
int temp = values[i];
String word = words[i];
values[i] = values[j];
words[i] = words[j];
values[j] = temp;
words[j] = word;
i++; j--;
}
}
if(low < i - 1) QuickSortWords(values, words, low, i - 1);
if(i < high) QuickSortWords(values, words, i, high);
}
public static String[] wordSort(String[] words) {
int[] values = new int[words.length];
for(int i = 0; i < words.length; i++)
values[i] = wordValue(words[i]);
QuickSortWords(values, words, 0, words.length - 1);
return words;
}
2
u/lesleh May 15 '12
Why not just use Arrays.sort()?
2
u/DisasterTourist May 15 '12
Brilliant idea. Makes it a lot easier.
Here's the simple answer to the question in Java.
public static void main(String args[]) { Challenge_51_Easy driver = new Challenge_51_Easy(); String a = "za"; String b = "aaa"; String names[] = {a, b}; Arrays.sort(names); }0
u/lesleh May 16 '12
What exactly is wrong with using the functionality provided to you by your programming language of choice?
1
u/ret0 May 14 '12
C:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int mytotal(const char *str){
int total=0;
for(;*str;str++)
total+=(*str)-(islower(*str)?96:64);
return total;
}
int mycmp(const void *a, const void *b){
return mytotal(*(const char **)b)-mytotal(*(const char **)a);
}
int main(int argc, char **argv){
qsort((void *)(argv+1),argc-1,sizeof(char *),mycmp);
for(int n=1;n<argc;n++){
printf("%s\n",argv[n]);
}
return 0;
}Compile with:
$ gcc -std=c99 -o mysort mysort.c
Run with:
$ ./mysort Hat Shoe
1
u/bh3 May 14 '12
Python:
def getSorted(l):
m = [(sum(ord(c)-ord('a')+1 for c in s.lower())/float(len(s)),s) for s in l]
return [s[1] for s in sorted(m, key=lambda s: s[0])]
1
u/StorkBaby May 14 '12 edited May 14 '12
Python, probably too much code here. edit: space before the code.
## generates the value of the word
## switch added for weighted extra credit
def word_val(word, weighted):
val = 0
for letter in string.lower(word):
val += string.find(string.lowercase, letter)
if weighted == True:
val = val/len(word)
return(val)
## creates a dictionary with the values
## will handle duplicate word values gracefully
def word_value(word_list, weighted=False):
coll = {}
for w in word_list:
temp_val = word_val(w, weighted)
if not temp_val in coll:
coll[temp_val] = []
coll[temp_val].append(w)
return(coll)
## prints the dictionary of values[words]
def word_order(word_dict):
ordered = []
key_list = word_dict.keys()
key_list.sort()
for k in key_list:
for w in word_dict[k]:
ordered.append(w)
return(ordered)
## usage
test = ["test", "spaz", "booger", "foo", "bar"]
print(word_order(word_value(test)))
print(word_order(word_value(test, True)))
1
u/atheistscansuckit May 14 '12
One liner(each) in python. Wouldn't be hard to take the list from a file and keep it a one liner
print map(lambda z: z[1],sorted(map(lambda y: (lambda x: (sum([ord(l)-ord('a')+1 for l in x])/len(x))(y),y),'hat,shoe'.split(','))))
print map(lambda z: z[1],sorted(map(lambda y: (lambda x: sum([ord(l)-ord('a')+1 for l in x])(y),y),'hat,shoe'.split(','))))
1
u/emcoffey3 May 14 '12
Using C# and LINQ:
using System.Collections.Generic;
using System.Linq;
namespace RedditDailyProgrammer
{
public static class Easy052
{
public static List<string> OrderBySum(List<string> list)
{
return list.OrderBy(s => StringSum(s)).ToList();
}
public static int StringSum(string s)
{
return s.ToUpper().ToCharArray().Select(c =>
{
return (int)(c - 64);
}).Sum();
}
public static List<string> OrderBySumExtraPoints(List<string> list)
{
return list.OrderBy(s => StringSumExtraPoints(s)).ToList();
}
public static double StringSumExtraPoints(string s)
{
return s.ToUpper().ToCharArray().Select(c =>
{
return (int)(c - 64);
}).Sum() / s.Length;
}
}
}
1
May 14 '12
C. Solves the bonus question if BONUS_QUESTION is defined when compiling, using a preprocessor trick.
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#define BONUS_QUESTION
int char_score(char c) {
if (isalpha(c))
return (tolower(c) - 'a' + 1);
return 0;
}
float word_score(char *s) {
int i; float n = 0.0;
for (i = 0; s[i]; i++)
n += char_score(s[i]);
#ifdef BONUS_QUESTION
n /= (float) i;
#endif
return n;
}
int word_score_cmp(const void *a, const void *b) {
float f = word_score(*(char**)a) - word_score(*(char**)b);
return (f < 0.0) ? -1 : (f > 0.0);
}
int main(int argc, char *argv[]) {
int i;
argv++; /* skip program name */
qsort(argv, argc - 1, sizeof(char*), word_score_cmp);
for (i = 0; argv[i]; i++)
printf("%10s = %3.2f\n", argv[i], word_score(argv[i]));
return 0;
}
1
u/Rapptz May 15 '12 edited May 15 '12
#include <iostream>
#include <string>
#include <algorithm>
char alphabet[26] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k',
'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' };
int sumof(std::string s) {
int sum1 = 0;
transform(s.begin(), s.end(), s.begin(), ::tolower);
for(int i = 0; i<s.length(); i++) {
for(int j=1; j<27; j++) {
if (s[i] == alphabet[j-1])
sum1+=j;
}
}
return sum1;
}
int main() {
using namespace std;
string a, b;
cout << "Input a string: ";
getline(cin,a);
int a1 = sumof(a);
cout << "Input another string: ";
getline(cin,b);
int b1 = sumof(b);
if(b1 > a1)
cout << "The largest string sum is " << b << " with a sum of " << b1 << " then " << a << " with a sum of " << a1 << endl;
else
cout << "The largest string sum is " << a << " with a sum of " << a1 << " then " << b << " with a sum of " << b1 << endl;
}
1
u/totallygeek May 15 '12 edited May 15 '12
Edit Put in the code for extra points
Bash:
#!/bin/sh
function calcWordValue() {
wordTotal=0
divTotal=0
str=`echo $1 | tr '[A-Z]' '[a-z]'`
strLen=${#str}
strSteps=$((strLen-1))
for x in `seq 0 ${strSteps}` ; do
oneChar=${str:x:1}
oneCharVal=$( printf "%d" "'${oneChar}" )
oneCharVal=$((oneCharVal-96))
wordTotal=$((wordTotal+oneCharVal))
done
divTotal=$((wordTotal/strLen))
echo "${str} ${strLen} ${wordTotal}" >> $redditFile1
echo "${str} ${strLen} ${divTotal}" >> $redditFile2
}
redditFile1="/tmp/20120514e-1.txt"
redditFile2="/tmp/20120514e-2.txt"
rm -f $redditFile1 $redditFile2
for word in $@ ; do
calcWordValue ${word}
done
echo " Sorted by Character Value Summation"
for workLine in `sort -k3 -u < $redditFile1 | tr ' ' ':'`; do
str=`echo $workLine | cut -d ':' -f 1`
strLen=`echo $workLine | cut -d ':' -f 2`
wordTotal=`echo $workLine | cut -d ':' -f 3`
echo " ${str}: Length=${strLen} Value=${wordTotal}"
done
echo ; echo " Sorted by Word Value Divided by Length"
for workLine in `sort -k3 -u < $redditFile2 | tr ' ' ':'`; do
str=`echo $workLine | cut -d ':' -f 1`
strLen=`echo $workLine | cut -d ':' -f 2`
divTotal=`echo $workLine | cut -d ':' -f 3`
echo " ${str}: Length=${strLen} Value=${divTotal}"
doneOutput(s):
[sjain@bandarji dailyprogrammer]$ ./20120514e.sh Shoe Hat Sorted by Character Value Summation hat: Length=3 Value=29 shoe: Length=4 Value=47 Sorted by Word Value Divided by Length shoe: Length=4 Value=11 hat: Length=3 Value=9
4
u/SpontaneousHam May 14 '12
Hey, my challenge!