Write a hash function for Morse Code

7

Your goal is to write a hash function, that accepts morse code character and returns a hash code that you get to define.

You can be sure, passed string will be:

  • One of the Latin characters (A-Z) encoded into Morse Code using . and -, or
  • One of the digits (0-9) encoded into Morse Code using . and -, or
  • Empty

So, there could be any of 37 different strings passed to you.

Requirements:

  • The returned number should be unique for all 37 strings
  • For empty string the function should return 0

Score:

  1. Initially, you have a 100 points.
  2. You will lose
    • 1 point for every bitwise operator in your code
    • 2 points for every addition (subtraction) operator in your code (operators in loop clauses (e.g. inside for(;;) or while() don't count)
    • 4 points for every multiplication (division, modulo, etc) operator
    • 6 points for every if (else) statement
    • 8 points for every loop statement (including loops in the called functions. You can presume that any called function has no more than one loop)
    • 12 points for every conditional operator
    • 200 points for using a built-in hash function

Bonuses:

  • If all numbers, produced by your function are less than N, you will get additional 137 - N points (of course, if the bonus is positive)

Winners:

Score matters, but be creative!


Example:

Score: 100 - 5*2 - 3*4 - 8 + (137 - 134) = 73

I know, this could be improved by removing modulo operator and make a loop starts from 1, but this is just an example

#include <iostream>
#include <map>
#include <set>

std::size_t hash_morse(const std::string& s)
{
    std::size_t ans = 0;

    for(std::size_t i = 0; i < s.size(); ++i)
    {
        ans += (s.at(i) - '-' + 2) * (i + 1) * (i + 1);
    }

    return ans % 134;
}

int main()
{
    std::map<std::string, char> m
    {
        {"",     0},
        {".-",   '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'},

        {".----",    '1'},
        {"..---",    '2'},
        {"...--",    '3'},
        {"....-",    '4'},
        {".....",    '5'},
        {"-....",    '6'},
        {"--...",    '7'},
        {"---..",    '8'},
        {"----.",    '9'},
        {"-----",    '0'}
    };

    std::map<std::size_t, std::string> hashes;

    for(const auto& elem: m)
    {
        auto hash = hash_morse(elem.first);

        if(hashes.find(hash) != hashes.end())
        {
            std::cout << "Collision" << std::endl;
            std::cout << '"' << hashes[hash] << R"(" and ")" << elem.first << '"' << std::endl;
            std::cout << "Hash: " << hash << std::endl;
            std::cout << std::endl;
        }
        else
        {
            hashes[hash] = elem.first;
        }
    }

    std::cout << "Total amount of collisions: " << (m.size() - hashes.size()) << std::endl;

    return 0;
}

awesoon

Posted 2014-01-31T12:31:15.807

Reputation: 189

Question was closed 2017-01-29T16:14:09.773

1What do you mean by "Score matters, but be creative"? I'm assuming the highest score wins, but you may want to clarify that. Is creativity solely a tie-breaker? If not, then it's not objective as is. – nyuszika7h – 2015-01-03T19:25:06.063

@soon Make sure you consider how well defined your scoring system is for more esoteric languages. Taking Brain-Flak as an example: Addition in Brain-Flak is implicit so it technically does not involve putting a addition operator in your code. At the same time it is done automatically so most of the results are not actually used. Also they way if clauses are made in Brain-Flak involves making a loop that never will run more than once. Would that count as a loop or an if/else and how should someone know for esoteric languages in general without asking?

– 0 ' – 2017-01-29T16:06:50.820

1

Although this isn't an exact duplicate of Morse code to standard output, it's close enough that most answers will be portable both ways.

– Peter Taylor – 2014-01-31T12:46:57.947

Wait, does string find/replace count as a loop? – Doorknob – 2014-01-31T13:24:32.890

By "binary operation" did you mean "bitwise operation"? Addition and multiplication are binary operations. – Kendall Frey – 2014-01-31T13:25:16.430

@DoorknobofSnow I think 'scanning' a string, and 'looping over' a string are semantically equivalent. – primo – 2014-01-31T13:30:27.073

@KendallFrey, yes, it was a typo. Thanks – awesoon – 2014-01-31T13:36:05.757

@DoorknobofSnow, yes. I've edited the post, thank you. – awesoon – 2014-01-31T13:44:51.610

What do you mean by "Hash code" is that like a hash function (that we get to define?), or is that some term in Morse? – McKay – 2014-01-31T13:57:02.567

"•If all numbers, produced by your function less than N" What? – McKay – 2014-01-31T13:58:39.043

"•Returned number should be unique for all strings" so that means that long isn't a valid return type? because there are more than 2^64 different possible strings? – McKay – 2014-01-31T14:00:36.833

We lose points for each operation that the program performs, or for each operator that we put into our code? – McKay – 2014-01-31T14:01:53.577

This phrase doesn't make sense: "(including loops in the called functions. Guess, that function has no more than one loop)" – McKay – 2014-01-31T14:02:34.080

@McKay, 1) yes, it's a hash function. 2) It means, that function should return numbers in range [0, N) for all correct strings. 3) Unique for all strings, that satisfies given requirements. 4) For each operator that we put into our code. 5) I mean, we don't know the number of loops in the called function. So, we guess, that called function has no more than one loop. – awesoon – 2014-01-31T14:09:37.177

2I'm pretty sure as soon as you remove loops, you remove turing completeness(recursion is still looping). – Cruncher – 2014-01-31T14:10:44.257

So, the objective is to define our own hash function? The phrase "return its hash code" implies that there already exists a hash code that we are to return, but no mention of what this hash code actually is. I presume that this implication is incorrect and that we get to define our own hash function? – McKay – 2014-01-31T14:11:53.020

@McKay, yes, the goal is to define a hash function. I'm going to rephrase it, thank you. – awesoon – 2014-01-31T14:15:10.217

I suggested a series of edits. That seemed easier than asking a hundred questions. – McKay – 2014-01-31T14:20:55.547

@soon You might want to clarify if all values produced by the hash should be unsigned (i.e. positive). You may also consider penalizing or disallowing direct hash look-ups.

– primo – 2014-01-31T15:55:55.023

Answers

9

Arguably perfect score

There are some possible loopholes in the scoring system. In particular,

8 points for every loop statement (including loops in the called functions. You can presume that any called function has no more than one loop)

According to PHP documentation,

array() is a language construct used to represent literal arrays, and not a regular function.

So it's arguable that

$hash = array(
    '' => 0,
    '.-' => -1,
    ...
);
return $hash[$morse];

contains no called functions and should score a perfect 100 + (137 - 1) = 236 points.

Peter Taylor

Posted 2014-01-31T12:31:15.807

Reputation: 41 901

Does array look up implicitly use a for loop or hash? – Rohan Jhunjhunwala – 2017-01-29T03:43:21.533

1@RohanJhunjhunwala, I don't know how it's implemented. FWIW nowadays I would cast a close vote and ask OP to sandbox the question rather than posting a protest answer, but that's a sign of how the site culture has changed. – Peter Taylor – 2017-01-29T09:02:02.230

I think this answer demonstrates that array/hash look-up either needs to be disallowed, or heavily penalized. – primo – 2014-01-31T15:38:34.500

15I would go further and say that it demonstrates that attempting to write scoring systems based around language constructs is doomed to fail unless you restrict people to using one language. – Peter Taylor – 2014-01-31T15:39:57.093

7

bash — 236 points

I understand there's some griping over using negative numbers, so have revised:

echo '' '[morse code]'|grep -o ' [\.-]*'|tr -t '.-' '19'|sed 's/ /0./g'|awk '{printf("%g\n",$0)}'

Will generate codes from 0.1 to 0.99999 for valid Morse Code and 0 for empty input.

e.g.

$ echo '' '. - .. -- .-.- -.-. ..... -----'|grep -o ' [\.-]*'|tr -t '.-' '19'|sed 's/ /0./g'|awk '{printf("%g\n",$0)}'
0.1
0.9
0.11
0.99
0.1919
0.9191
0.11111
0.99999

As per specs, empty input '' returns 0:

$ echo '' ''|grep -o ' [\.-]*'|tr -t '.-' '19'|sed 's/ /0./g'|awk '{printf("%g\n",$0)}'
0

Points Calculation

Starting with 100, deduct:

  • 1 point for every bitwise operator - none
  • 2 points for every addition (subtraction) operator - none
  • 4 points for every multiplication (division, modulo, etc) operator - none
  • 6 points for every if (else) statement - none
  • 8 points for every loop statement - none
  • 12 points for every conditional operator - none
  • 200 points for using a built-in hash function - none

So still have 100 points.

Bonus Calculation

All numbers are less than 1 (largest is 0.99999 for ----- a.k.a. Morse Code Zero), so the bonus is 137 - 1 or 136 points, again for a total of 236 points.


bash — 236 points

echo '' '[morse code]'|grep -o ' [\.-]*'|tr -t '.-' '67'|sed 's/ /-0/g'|awk '{printf("%d\n",$0)}'

Will generate codes from -77777 to -6 for valid Morse Code and 0 for empty input.

e.g.

$ echo '' '. - ..--. -..- .--- .. -..-. .. -----'|grep -o ' [\.-]*'|tr -t '.-' '67'|sed 's/ /-0/g'|awk '{printf("%d\n",$0)}'
-6
-7
-66776
-7667
-6777
-66
-76676
-66
-77777

As per specs, empty input '' returns 0:

$ echo '' ''|grep -o ' [\.-]*'|tr -t '.-' '67'|sed 's/ /-0/g'|awk '{printf("%d\n",$0)}'
0

Points Calculation

Starting with 100, deduct:

  • 1 point for every bitwise operator - none
  • 2 points for every addition (subtraction) operator - none
  • 4 points for every multiplication (division, modulo, etc) operator - none
  • 6 points for every if (else) statement - none
  • 8 points for every loop statement - none
  • 12 points for every conditional operator - none
  • 200 points for using a built-in hash function - none

So still have 100 points.

Bonus Calculation

All numbers are less than 1 (largest is 0 for an empty input), so the bonus is 137 - 1 or 136 points for a total of 236 points.

user15259

Posted 2014-01-31T12:31:15.807

Reputation:

You realize that every valid hash which negates its output would automatically have a bonus of 136. Clearly, the author intended the maximum bonus to be 100. – primo – 2014-01-31T16:11:00.630

From the specs "Your goal is to write a hash function, that accepts Morse Code characters and returns a hash code that you get to define." Standard hash codes, e.g. from md5 or sha1 can be interpreted as negative numbers, especially in languages without unsigned types like Java or Basic. There are two requirements: the returned number should be unique for all 37 strings, and for empty strings the function should return 0. Both are met. – None – 2014-01-31T16:22:18.983

There are 36 morse codes in this challenge. The 137-N formula should suggest that the author is referring to a positive, integer result. By skirting the requirements you are just wasting your time, because he will just write his intentions better as soon as he sees answers such as these. – Tobia – 2014-01-31T23:00:42.667

6

Ruby 100 - 6 (one if/else) - 2 (one subtraction) = 92 + 75 (largest value is 62) = 167 (159 if string find/replace counts as looping)

code = gets.chomp
if code.empty?
  p -1
else
  p ('1' + code.gsub(/./){|c| c.ord - 45 }).to_i(2)
end

Simply does a find/replace on the string, but replaces each character with its ASCII code - 45. This turns - into 0 and . into 1. It then prepends a 1 (to handle leading zeroes) and parses this string as binary.

Doorknob

Posted 2014-01-31T12:31:15.807

Reputation: 68 138

Same comment as to primo: 137 - 63 = 74 for the bonus. (And clarification to question says that find/replace counts as looping). – Peter Taylor – 2014-01-31T14:57:53.897

5

GolfScript (143 164 192 points)

I was slightly wrong about the relationship with the other Morse question: this one is much much simpler.

2base

scores 100 - 8 points for an implicit loop = 92, with no bonus.

2base 87%

scores 100 - 4 points for a modulo - 8 points for an implicit loop + (137 - 82) bonus points for a total of 143 points.

That has two parameters which can potentially be optimised to improve the bonus. The best I've found so far is

46base 62%

for N=61 and a total of 164 points.

But it's possible to do even better.

2base MAGIC_STRING=

scores 100 - 8 points for an implicit loop + (137 - 37) bonus points for a total of 192 points, where MAGIC_STRING is a suitable 1427-character string literal:

"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1E\x0F\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x17\x18\v\x13\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x19\x11\x15\x0E!\x1C\x1F\x1D\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\e$#\r\"\f\x14\x1A\x00\x16\x00\x10 \x12\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\n\x00\t\x00\x00\x00\b\x00\x00\x00\x00\x00\x00\x00\a\x02\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x04\x00\x05\x06"

Peter Taylor

Posted 2014-01-31T12:31:15.807

Reputation: 41 901

@primo, that's what comes of copying the string from a command window output rather than redirecting to a file and copying from the file. = is not a looping function: it's an array indexing operation. No language that I know of implements those with a loop. – Peter Taylor – 2014-01-31T15:23:02.453

You're right. I Confused it with find. – primo – 2014-01-31T15:26:49.817

2

Perl - score = 165

print~-oct'0b1'.<>=~y/.-/10/r

Re-interpretting morse as binary, with a 1 prepended.

Score break-down

  • -1 - bitwise inversion (~)
  • -8 - loop statement (y)
  • +74 - the largest value produced is 62

primo

Posted 2014-01-31T12:31:15.807

Reputation: 30 891

I make 137 - 63 = 74 for the bonus. – Peter Taylor – 2014-01-31T14:53:37.737

180+ should be possible. Go go magic formula grinder. – primo – 2014-01-31T14:57:24.137

Actually, yes, you're right... – Peter Taylor – 2014-01-31T14:59:20.840

2

Scheme:

Initial 100 points and it has no reduction since there was no mention of switch/case there and the / is part of the number not an operator..

The output is a rational number between 0 and 1. Extra score would be 137-1=136.

Total score: 236

(define (hash-morse-code code)
  (case code
    (("") 0)
    ((".-") 1)
    (("-...") 1/2)
    (("-.-.") 1/3)
    (("-..") 1/4)
    ((".") 1/5)
    (("..-.") 1/6)
    (("--.") 1/7)
    (("....") 1/8)
    (("..") 1/9)
    ((".---") 1/10)
    (("-.-") 1/11)
    ((".-..") 1/12)
    (("--") 1/13)
    (("-.") 1/14)
    (("---") 1/15)
    ((".--.") 1/16)
    (("--.-") 1/17)
    ((".-.") 1/18)
    (("...") 1/19)
    (("-") 1/20)
    (("..-") 1/21)
    (("...-") 1/22)
    ((".--") 1/23)
    (("-..-") 1/24)
    (("-.--") 1/25)
    (("--..") 1/26)
    ((".----") 1/27)
    (("..---") 1/28)
    (("...--") 1/29)
    (("....-") 1/30)
    ((".....") 1/31)
    (("-....") 1/31)
    (("--...") 1/32)
    (("---..") 1/33)
    (("----.") 1/34)
    (("-----") 1/35)))

(hash-morse-code "...") => 1/19

Sylwester

Posted 2014-01-31T12:31:15.807

Reputation: 3 678

0

Java - 100 + 136 = 236

public static int hashMorse(String toHash) {
    switch (toHash){
        case ".-": //A
            return -36;
        case "-...": //B
            return -35;
        case "-.-.": //C
            return -34;
        case "-..": //D
            return -33;
        case ".": //E
            return -32;
        case "..-.": //F
            return -31;
        case "--.": //G
            return -30;
        case "....": //H
            return -29;
        case "..": //I
            return -28;
        case ".---": //J
            return -27;
        case "-.-": //K
            return -26;
        case ".-..": //L
            return -25;
        case "--": //M
            return -24;
        case "-.": //N
            return -23;
        case "---": //O
            return -22;
        case ".--.": //P
            return -21;
        case "--.-": //Q
            return -20;
        case ".-.": //R
            return -19;
        case "...": //S
            return -18;
        case "-": //T
            return -17;
        case "..-": //U
            return -16;
        case "...-": //V
            return -15;
        case ".--": //W
            return -14;
        case "-..-": //X
            return -13;
        case "-.--": //Y
            return -12;
        case "--..": //Z
            return -11;
        case ".----": //1
            return -10;
        case "..---": //2
            return -9;
        case "...--": //3
            return -8;
        case "....-": //4
            return -7;
        case ".....": //5
            return -6;
        case "-....": //6
            return -5;
        case "--...": //7
            return -4;
        case "---..": //8
            return -3;
        case "----.": //9
            return -2;
        case "-----": //0
            return -1;
        default:
            return 0;
    }
}

All those - signs don't count; they stand for the literal number. If you want to count them, then I'll just replace all those numbers with the binary literal (no minuses then).

Switches are free according to the question; neither an if nor an else. If you don't want switches, I'll just replace it with a HashMap

The largest possible number is 0, for the empty string or invalid strings.


Don't like negative numbers? This works (score of 200):

public static int hashMorse(String toHash) {
    switch (toHash){
        case ".-": //A
            return 36;
        case "-...": //B
            return 35;
        case "-.-.": //C
            return 34;
        case "-..": //D
            return 33;
        case ".": //E
            return 32;
        case "..-.": //F
            return 31;
        case "--.": //G
            return 30;
        case "....": //H
            return 29;
        case "..": //I
            return 28;
        case ".---": //J
            return 27;
        case "-.-": //K
            return 26;
        case ".-..": //L
            return 25;
        case "--": //M
            return 24;
        case "-.": //N
            return 23;
        case "---": //O
            return 22;
        case ".--.": //P
            return 21;
        case "--.-": //Q
            return 20;
        case ".-.": //R
            return 19;
        case "...": //S
            return 18;
        case "-": //T
            return 17;
        case "..-": //U
            return 16;
        case "...-": //V
            return 15;
        case ".--": //W
            return 14;
        case "-..-": //X
            return 13;
        case "-.--": //Y
            return 12;
        case "--..": //Z
            return 11;
        case ".----": //1
            return 10;
        case "..---": //2
            return 9;
        case "...--": //3
            return 8;
        case "....-": //4
            return 7;
        case ".....": //5
            return 6;
        case "-....": //6
            return 5;
        case "--...": //7
            return 4;
        case "---..": //8
            return 3;
        case "----.": //9
            return 2;
        case "-----": //0
            return 1;
        default:
            return 0;
    }
}

Justin

Posted 2014-01-31T12:31:15.807

Reputation: 19 757

HashMap definitely isn't free. It has loops in both put and get. – Peter Taylor – 2014-01-31T23:12:22.240

@PeterTaylor what about python's dictionaries? Can I use those? – Justin – 2014-02-01T00:53:46.087

Probably, although then it's going to look very similar to my PHP answer. switch is more interesting because no-one else had done it. – Peter Taylor – 2014-02-01T07:54:37.377

0

Java - 100 + 136 = 236

public static int hash(String morse){
    try{
        morse.charAt(0);
    }catch (IndexOutOfBoundsException e){
        return 0;
    }
    return Integer.parseInt("-1" + help(morse), 2);
}
private static String help(String morse) {
    int a = 0;
    try {
        a = (int) morse.charAt(0);
    } catch (IndexOutOfBoundsException e) {
        return "";
    }
    a = Integer.parseInt(String.valueOf(Integer.toString(a, 2).charAt(4)));
    return a + help(morse.substring(1));
}

call hash(someString); to use this function. I'm working on a loop-free alternative to Integer.parseInt and Integer.toString.

I avoided the penalties by:

  • using recursion instead of loops
  • using Strings and String concatenation instead of numbers

So I get 100 + 136 as the largest output is 0.

Justin

Posted 2014-01-31T12:31:15.807

Reputation: 19 757

They use loops. So does String.format.

– Peter Taylor – 2014-01-31T23:10:27.780

0

JavaScript, 217pts

replace : Minus 8pts (loop)
replace : Minus 8pts (loop)
/ 100000: Minus 4pts (division)

100 - 20 = 80 + (137 - 0) = 217

function mc2(s) {
    return s.replace(/\./g,'1').replace(/-/g,'2') / 100000
}

JavaScript 199pts

for     : Minus  8pts (loop)
r+=     : Minus  2pts (addition)
(c>'-') : Minus  6pts (if)
c>'-'   : Minus 12pts (conditional operator)
:2      : Minus  6pts (else)
r/      : Minus  4pts (division)

100-38pts = 62pts + (137-0) = 199pts

function mc2(s) {
    r=''
    for(i=0;(c=s[i]);i++)r+=(c>'-')?1:2
    return r/100000
}

wolfhammer

Posted 2014-01-31T12:31:15.807

Reputation: 1 219

-1

Python, 236

Now, Peter Taylor claims to have a perfect score. But really, he's only got 200. Negative numbers all being smaller than zero, my bonus is 137-1, so this solution is 36 points better.

F = lambda s:-eval(''.join([
'12340'[s[0:].find('-')],'12340'[s[0:].find('.')],
'12340'[s[1:].find('-')],'12340'[s[1:].find('.')],
'12340'[s[2:].find('-')],'12340'[s[2:].find('.')],
'12340'[s[3:].find('-')],'12340'[s[3:].find('.')],
'12340'[s[4:].find('-')],'12340'[s[4:].find('.')]]))

boothby

Posted 2014-01-31T12:31:15.807

Reputation: 9 038

Does find not contain a loop? – Peter Taylor – 2014-01-31T23:07:19.517

Ah, missed the bit on functions. – boothby – 2014-02-01T00:21:45.397

Waitaminute. We can assume "no more than one"? How 'bout I assume zero, which is certainly no more than one, and don't change my answer in the least. – boothby – 2014-02-01T00:23:17.827

I don't think that's a plausible interpretation. – Peter Taylor – 2014-02-01T07:24:25.340

I don't think so either, but that's what a literal reading of the rules suggests. I think I'm being generous, actually, by not updating my score to reflect an assumption of a negative number of loops in the function calls. – boothby – 2014-02-01T15:49:56.390