# They call me Inspector Morse

Your mission, should you choose to accept it, is to decide whether a given input string is Dot-heavy, or Dash-heavy.

A string is dot-heavy when its morse representation contains more dots than dashes. For example, the letter E is a single dot, which means it is Dot-heavy.

# Input

• The input string will only contain characters in the range of [a-z] or [A-Z]. You can decide if they should all be upper case, or all lower case. AAA is fine, aaa is fine, aAa is not.
• The input string will always be at least 1 character in length.
• You may assume that input strings will never have an equal amount of dots and dashes.

# Output

You should return Truthy for inputs that contain more dot characters.
You should return Falsy for inputs that contain more dash characters.
Edit: I will allow a positive value for dot and a negative value for dash as well.

# Test cases

| input | morse representation | result          |
|------------------------------------------------|
| S     | ...                  | Truthy          |
| k     | -.-                  | Falsy           |
| HELLO | .... . .-.. .-.. --- | Truthy          |
| code  | -.-. --- -.. .       | Falsy           |


# Reference

This is . Shortest code in bytes wins.

• Related – Bassdrop Cumberwubwubwub Mar 11 '19 at 16:35
• Can we return a value above 0 for dotheavy and a negative value for dash-heavy? – Gymhgy Mar 11 '19 at 20:20
• @EmbodimentofIgnorance That works for me, as long as you specify it in your post. I don't think it usually passes the truthy falsy test but it feels like a good solution in this case so I will allow it – Bassdrop Cumberwubwubwub Mar 12 '19 at 8:38

# APL (Dyalog Extended), 24 15 bytesSBCS

-9 thanks to Ven

Anonymous tacit prefix function taking uppercase as argument.

>/'.-'⍧∊∘⌂morse


Try it online!

⌂morse convert to list of Morse strings
∘ then
∊ϵnlist (flatten)
'.-'⍧ count the number of dots and dashes in that
>/ more dots than dashes? (lit. greater-than reduction)

• why not have Extended preload dfns by default? – ngn Mar 13 '19 at 19:53
• @ngn It is now built-in – Adám Apr 11 '19 at 12:02

# IBM PC DOS, 8088 assembly, 54 35 bytes

-19 bytes using the difference method

ac2c 41d0 d8d7 7206 51b1 04d2 e859 240f 2c03 02e0 e2ea 3534 4527 4125 1303 1462 4523 13


Unassembled:

; compare dashes and dots in a morse code string
; input:
;   I: pointer to input string (default SI)
;   IL: length of input string (default CX)
;   TBL: pointer to data table (default BX)
; output:
;   Sign/OF flags: Dot-heavy: SF == OF (JGE), Dash-heavy: SF != OF (JL)
MORSE_DD    MACRO   I, IL, TBL
LOCAL   LOOP_LETTER, ODD
IFDIFI <I>,<SI>     ; skip if S is already SI
MOV  SI, I              ; load string into SI
ENDIF
IFDIFI <IL>,<CX>    ; skip if IL is already CX
MOV  CX, IL             ; set up loop counter
ENDIF
IFDIFI <TBL>,<BX>   ; skip if TBL is already BX
MOV  BX, OFFSET TBL     ; load letter table into BX
ENDIF
LOOP_LETTER:
;AND  AL, 0DFH           ; uppercase the input letter (+2 bytes)
SUB  AL, 'A'            ; convert letter to zero-based index
RCR  AL, 1              ; divide index by 2, set CF if odd index
XLAT                    ; lookup letter in table
JC   ODD                ; if odd index use low nibble; if even use high nibble
PUSH CX                 ; save loop counter (since SHR can only take CL on 8088)
MOV  CL, 4              ; set up right shift for 4 bits
SHR  AL, CL             ; shift right
POP  CX                 ; restore loop counter
ODD:
AND  AL, 0FH            ; mask low nibble
SUB  AL, 3              ; unbias dash/dot difference +3 positive
ADD  AH, AL             ; add letter difference to sum (set result flags)
LOOP LOOP_LETTER
ENDM

TBL DB 035H, 034H, 045H, 027H, 041H, 025H, 013H, 003H, 014H, 062H, 045H, 023H, 013H


Explanation

Implemented in Intel/MASM syntax as a MACRO (basically a function), using only 8088 compatible instructions. Input as uppercase string (or +2 bytes to allow mixed-case), output Truthy/Falsy result is SF == OF (use JG or JL to test).

The letter difference table values are stored as binary nibbles, so only takes 13 bytes in total.

Original (54 bytes):

; compare dashes and dots in a Morse code string
; input:
;   I: pointer to input string (default SI)
;   IL: length of input string (default CX)
;   TBL: pointer to data table
; output:
;   Carry Flag: CF=1 (CY) if dot-heavy, CF=0 (NC) if dash-heavy
MORSE_DD    MACRO   I, IL, TBL
LOCAL   LOOP_LETTER
IFDIFI <I>,<SI>     ; skip if S is already SI
MOV  SI, I              ; load string into SI
ENDIF
IFDIFI <IL>,<CX>    ; skip if IL is already CX
MOV  CX, IL             ; set up loop counter
ENDIF
MOV  BX, OFFSET TBL     ; load score table into BX
XOR  DX, DX             ; clear DX to hold total score
LOOP_LETTER:
;AND  AL, 0DFH           ; uppercase the input letter (+2 bytes)
SUB  AL, 'A'            ; convert letter to zero-based index
XLAT                    ; lookup letter in table
MOV  AH, AL             ; examine dot nibble
AND  AH, 0FH            ; mask off dash nibble
PUSH CX                 ; save loop counter (since SHR can only take CL)
MOV  CL, 4              ; set up right shift for 4 bits
SHR  AL, CL             ; shift right
POP  CX                 ; restore loop counter
LOOP LOOP_LETTER
CMP  DL, DH             ; if dot-heavy CF=1, if dash-heavy CF=0
ENDM

; data table A-Z: MSN = count of dash, LSN = count of dot
TBL DB 011H, 013H, 022H, 012H, 001H, 013H, 021H, 004H, 002H
DB 031H, 021H, 013H, 020H, 011H, 030H, 022H, 031H, 012H
DB 003H, 010H, 012H, 013H, 021H, 022H, 031H, 022H


Explanation

Implemented in Intel/MASM syntax as a MACRO (basically a function), using only 8088 compatible instructions. Input as string, output Truthy/Falsy result in Carry Flag. Score table contains the number of dashes and dots per letter.

Input is upper case. Add 2 bytes to take lower or mixed case.

Example Test Program (as IBM PC DOS standalone COM executable)

    SHR  SI, 1              ; point SI to DOS PSP
MOV  CL, AL             ; set up loop counter in CH
DEC  CX                 ; remove leading space from letter count

MORSE_DD SI, CX, TBL    ; execute above function, result is in CF

MOV  DX, OFFSET F       ; default output to "Falsy" string
MOV  DX, OFFSET T       ; otherwise CF=1, set output to "Truthy" string
DISP_OUT:
MOV  AH, 09H            ; DOS API display string function
INT  21H
RET

T   DB "Truthy$" F DB "Falsy$"


Example Output:

Or Try it Online! I'm not aware of an online TIO to direct link to a DOS executable, however you can use this with just a few steps:

2. Go to https://virtualconsoles.com/online-emulators/DOS/
4. Type DD Hello or DD code to your heart's content
• I might be missing something, but does that macro not assume AH = 0 upon entry? Granted, that assumption is valid when using the test program. – gastropner Mar 12 '19 at 18:07
• Good eye! The assumption is based on DOS execution initial startup register values, which for almost all versions of DOS is 0000h for AX source: fysnet.net/yourhelp.htm – 640KB Mar 12 '19 at 18:24
• From one assembly golfer to another: nice! Extra style points for using purely 8088-compatible instructions. That's a platform where code golfing is largely equivalent to optimization, and truly a lost art. Nice use of XLAT to do exactly what it is meant to do. If you were actually optimizing for speed over size, you'd want to do WORD-sized lookups. This is still a speed win even on the 8088 with its anemic 8-bit external bus, because you are doubling the throughput without increasing the code size, save for an XCHG instruction or two. – Cody Gray Mar 12 '19 at 23:31
• @CodyGray thanks! It's always fun when a challenge lines up nicely with the platform and instruction set. Plus it is neat when you can accomplish something on the original PC's 8088 in 1 byte (such as XLAT), even though it takes 6 bytes to do a bitwise shift right 4 places (inside a LOOP). – 640KB Mar 13 '19 at 15:41
• Yup. For performance, you would definitely want to do 4 separate shifts by 1, eliminating the push and pop. It's not even that many more bytes (+2), so overall a net win, but not good for golfing. The real fun comes when the challenge doesn't line up with the ISA, and you have to stretch your mind to find new, innovative ways of applying the existing building blocks. The 1-byte string instructions are really nice on 8088 for performance and also golfing. I use them in real code. XLAT is one I don't often find much use for, I guess because modern architectures have biased me against LUTs. – Cody Gray Mar 13 '19 at 22:25

# Java (JDK), 13112411084 64 bytes

Interestingly, "dot" is dash-heavy and "dash" is dot-heavy.

Takes input in all caps as an IntStream (scroll down for a version with an actual String for an extra 8 bytes). I've had quite a lot of help golfing this one: Thanks to Expired Data for golfing 20 bytes, to Neil for golfing 26 bytes, to Olivier Grégoire for golfing 18 bytes and to Kevin Cruijssen for golfing 2 bytes.

Contains 26 unprintable characters inside the double quotes.

c->c.map(a->"".charAt(a-65)-4).sum()>0


Try it online!

Ungolfed:

c -> // lambda taking input as an IntStream in upper case and returning a boolean
c.map(a -> "" // map each character's ASCII value to its net dot impact (unprintable characters here)
.charAt(a - 65) // translate the ASCII code into a zero-based index into the above string (65 is 'A')
- 4) // unprintables are > 0, this restores the proper values
.sum() > 0 // add up all the values, positive sum indicates a dot-heavy input string


# Java (JDK), 13112411084 72 bytes

For purists; takes input as a String. Thanks to Expired Data for golfing 20 bytes, to Neil for golfing 26 bytes and to Olivier Grégoire for golfing 10 bytes.

s->s.chars().map(a->"".charAt(a-65)-4).sum()>0


Try it online.

Ungolfed:

s -> // lambda taking input as a String in upper case and returning a boolean
s.chars() // convert to a stream of characters
.map(a -> "" // map each character's ASCII value to its net dot impact (unprintable characters here)
.charAt(a - 65) // translate the ASCII code into a zero-based index into the above string (65 is 'A')
- 4) // unprintables are > 0, this restores the proper values
.sum() > 0 // add up all the values, positive sum indicates a dot-heavy input string

• 124 bytes – Expired Data Mar 11 '19 at 17:32
• Make that 111 bytes – Expired Data Mar 11 '19 at 21:53
• Why not use "35344527512513031462452313".charAt(a-65)-51? – Neil Mar 11 '19 at 22:13
• 66 bytes – Olivier Grégoire Mar 12 '19 at 9:50
• @OlivierGrégoire Your 66-byte is actually 65, since you forgot to remove the trailing semi-colon. 1 more byte can be saved by using unprintable characters however: 64 bytes – Kevin Cruijssen Mar 12 '19 at 10:18

# Jelly, 21 bytes

Oị“ÆġwıMƥ)ɠịṙ{’D¤Æm>4


Try it online!

### How?

Oị“ÆġwıMƥ)ɠịṙ{’D¤Æm>4 - Link: list of characters ([A-Z]), S
“ÆġwıMƥ)ɠịṙ{’       -   base 250 integer = 14257356342446455638623624
D      -   to decimal digits
-   -- that is the number of dots less the number of dashes plus 4
-      ... for each of OPQRSTUVWXYZABCDEFGHIJKLMN
O                     - ordinals of S   e.g. "ATHROUGHZ" -> [65,84,72,82,79,85,71,72,90]
ị                    - index into (1-indexed & modular, so O gets the 79%26 = 1st item
-                                  or A gets the 65%26 = 13th item
Æm   - arithmetic mean
>4 - greater than 4?


# 05AB1E, 22 21 bytes

Saved a byte thanks to Kevin Cruijssen

SA•U(Õþć6Δ
»›I•‡3-O.±


Try it online!

Explanation

•U(Õþć6Δ
»›I•


is 35344527512513031462452313 compressed to base 255.

S              # split input into list of chars
‡       # transliterate
A             # the lowercase alphabet
•...•        # with the digits from the compressed string
3-     # subtract 3 from each
O    # then sum the result
.±  # and take the sign

• You can save a byte by replacing the map with S. – Kevin Cruijssen Mar 12 '19 at 7:44
• @KevinCruijssen: Thanks! I was sure I had tried that, but apparently not :) – Emigna Mar 12 '19 at 7:48
• Just for fun: the string usdgpsahsoaboutlopezgbidol (concatenation of 8 words from the dictionary) can be used to get the values: for each character $c$ in there: v = ord(c)*3%83%8. – Arnauld Mar 12 '19 at 11:26
• @Arnauld: Interesting! How did you find that out? Not by hand I hope :P – Emigna Mar 12 '19 at 11:38
• I brute-forced all word pairs and the longest match was aboutlopez. I then looked for other matches with the same multiplier and modulo. (So it's absolutely not guaranteed to be optimal.) – Arnauld Mar 12 '19 at 11:45

# C# (Visual C# Interactive Compiler), 47 bytes

n=>n.Sum(i=>("[E[LduRgmQSMK"[i%13]>>i%2*3)%8-3)


Uses Level River St's 'magic string'. Be sure to upvote their solution as well!

It's not everyday C# beats Ruby, Python, Javascript, C, Retina, and Perl!

Try it online!

# Jelly, 23 bytes

9“¡ȷṡẓh)ėḂYF@’ḃ_4ị@OS0<


Try it online!

# C (gcc), 84828179 75 bytes

Assumes all caps.

r;f(char*s){for(r=0;*s;r+="+-+,,-*/--*-)+(+),.*,-*+)+"[*s++%65]-43);s=r>0;}


Try it online!

# Python 2, 7370 69 bytes

lambda s:sum(int(0x21427b563e90d7783540f[ord(c)%25])-3for c in s)>0


Try it online!

Uppercase only

-3 bytes, thanks to Erik the Outgolfer

Both upper- and lowercase version:

# Python 2, 73 71 bytes

lambda s:sum(int(oct(0x1d7255e954b0ccca54cb)[ord(c)%32])-3for c in s)>0


Try it online!

# JavaScript (Node.js),  69  68 bytes

Expects the input string in uppercase. Returns $$\0\$$ or $$\1\$$.

s=>Buffer(s).map(n=>s+='30314624523133534452741251'[n%26]-3,s=0)|s>0


Try it online!

# Stax, 20 bytes

ÉBÜ◙ƒ╣<Hf6─òÉ¼säS╗◄↔


Run and debug it

Unpacked, ungolfed, and commented, it looks like this.

"45D.J57KBJa"I"    string literal with code points [52 53 68 46 74 53 55 75 66 74 97 34 73]
$flatten to string "52536846745355756674973473" ; push input @ get string characters at indices (using input codepoints as indices; lookups wrap around) :V arithmetic mean 53> is greater than 53  Run this one # Ruby, 64 bytes ->s{n=0;s.bytes{|i|n+=("[E[LduRgmQSMK"[i%13].ord>>i%2*3)%8-3};n}  Try it online! Uses a 13-byte magic string, 2 numbers 0..7 encoded in each byte. Subtract 3 for a range -3..4. The ASCII code for A (and also N) taken modulo 13 is by coincidence, zero. # Retina 0.8.2, 51 bytes TL35344527412513031462452313 .$*<>>>
+<>|><

^<


Try it online! Link includes test cases. Only accepts upper case (+6 bytes for mixed case). Shamelessly stealing @Arnauld's string but I was going to use the same algorithm anyway. Explanation:

TL35344527412513031462452313
.


Change each letter into the difference in numbers of dots and dashes, plus three, so O=0 and H=7.

$*<>>>  Represent the difference as that number of <s and three >s. (Sadly I can't use dots because they're special in regex.) +<>|><  Remove matched pairs of <s and >s. ^<  Check whether there are still any dots left. # Bash+coreutils, 64 60 bytes tr a-z 35344526512513031462452313|sed s/./\&z-+/g|dc -eIK?^p  Try it online! Takes a string in lowercase, outputs zero for falsy, nonzero for truthy # Explanation Uses tr and sed to create a dc program that looks like (for the example input 'hello'): IK6z-+4z-+5z-+5z-+0z-+^p IK Push 10, then 0 to the stack 6z-+ Push 6 (three more than the dots minus dashes in 'h'), subtract 3, and accumulate ... Do the same for all other letters, so the stack now has the total dots minus dashes ^ Raise 10 to this power - precision is zero so this turns negative/positive to falsy/truthy p Print result  • Golfed two bytes by just putting the dc in the pipeline rather than use command substitution, then another byte by replacing <space>3 with z (conveniently, I have 3 items on the stack at that point!) and another byte by replacing the quotes around my sed program with a single backslash to escape the & – Sophia Lechner Mar 11 '19 at 19:05 # R, 74 70 bytes f=utf8ToInt;sum(f("42433250265364746315325464")[f(scan(,''))-96]-52)<0  input should be lower case, returns TRUE or FALSE Try it online # TI-BASIC (TI-84), 111 bytes :Ans→Str1:"ABCDEFGHIJKLMNOPQRSTUVWXYZ→Str2:"35344527512513031462452312→Str3:0<sum(seq(expr(sub(Str3,inString(Str2,sub(Str1,X,1)),1)),X,1,length(Str1))-3  I used the same string for determining dot-heaviness as some of the other answers. Program returns truthy (1) if the input string is dot-heavy, falsy (0) if not. Input string must be in all-caps. Input is stored in Ans. Output is stored in Ans and is automatically printed out when the program completes. Ungolfed: :Ans→Str1 :"ABCDEFGHIJKLMNOPQRSTUVWXYZ→Str2 :"35344527512513031462452312→Str3 :0<sum(seq(expr(sub(Str3,inString(Str2,sub(Str1,X,1)),1)),X,1,length(Str1))-3  Example: "HELLO HELLO prgmCDGF3 1 "CODE CODE prgmCDGF3 0  Explanation: (TI-BASIC doesn't have comments, assume that ; indicates a commment) :Ans→Str1 ;store the input into Str1 :"ABCDEFGHIJKLMNOPQRSTUVWXYZ→Str2 ;store the uppercase alphabet into Str2 :"35344527512513031462452312→Str3 ;store dot-dash+3 for each letter into Str3 :0<sum(seq(expr(sub(Str3,inString(Str2,sub(Str1,X,1)),1)),X,1,length(Str1))-3 ;full logic sum( ;sum the elements of seq( ) ;the list evaluated by sub( ) ;the substring of Str3, ;Str3 inString( ), ;at the index of sub( ) ;the substring of Str1, ;Str1 X, ;starting at X 1 ;of length 1 Str2, ;in Str2 1 ;of length 1 expr( ), ;converted to an integer X, ;using X as the increment variable 1, ;starting at 1 length(Str1) ;ending at the length of Str1 -3 ;then subtract 3 from all elements in the list 0< ;then check if the sum is greater than 0 ;implicitly output the result  Note: The byte count of a program is evaluated using the value in [MEM]>[2]>[7] (124 bytes) then subtracting the length of the program's name, CDGF3, (5 bytes) and an extra 8 bytes used for storing the program: 124 - 5 - 8 = 111 bytes # Perl 5-pF, 53 bytes $p+=y/a-z/35344526512513031462452313/r-3for@F;$_=$p>0


Try it online!

# Factor, 66 bytes

: f ( s -- ? ) >morse [ [ 45 = ] count ] [ [ 46 = ] count ] bi < ;


Try it online!

# C++ (compiled with Visual Studio 2017) 171bytes

int f(string i){const char*c="1322131421130102123023121211210120032121323101112232";int j=0,h[2]={0};while(j<sizeof(i)/28)*h+=c[i[j]-97],h[1]+=c[i[j++]-71];return*h>h[1];}


if we take the main program that exists for test purposes into account as well its more.

this is the ungolfed "tidy" variant

#include "stdafx.h"
int main()
{
const int dotCount[] = {1,3,2,2,1,3,1,4,2,1,1,3,0,1,0,2,1,2,3,0,2,3,1,2,1,2};
const int dashCount[] = {1,1,2,1,0,1,2,0,0,3,2,1,2,1,3,2,3,1,0,1,1,1,2,2,3,2};
std::cout << "Enter String:\n";
std::string input;
std::cin >> input;
int inputsHeavyness[2] = { 0 };
for(int i = 0;i < sizeof(input)/sizeof(std::string);i++)
{
inputsHeavyness[0] += dotCount[input[i] - 'a'];
inputsHeavyness[1] += dashCount[input[i] - 'a'];
}
if (inputsHeavyness[0] > inputsHeavyness[1])
{
std::cout << "Dot Heavy\n";
}
else
{
std::cout << "Dash Heavy or Neutral\n";
}
return 0;
}


assumes all lowercase

• You may want to add a TIO link. (Also, I think you have a typo in the ungolfed code: this 22 should be 2.) – Arnauld Mar 12 '19 at 1:11
• yeah this may well be a typo. i guess i fixed that in the golfed version though. tio well i have no clue of that stuff (i think i looked at it once and it didnt feature the compiler i m using so results between vs2017 and tio would likely vary? no good at all) – der bender Mar 12 '19 at 1:15
• 145 bytes. Results may indeed vary between VS and TIO. It sometimes varies for me too, and I am actually using GCC (albeit MinGW). – gastropner Mar 12 '19 at 23:58
• Tweak of @ceilingcat for 131 bytes – gastropner Apr 15 '19 at 16:49
• Building on @gastropner 111 bytes Combined both arrays into one; "132... and "112... become "353... and 51 is the ASCII value of 3 – ceilingcat Apr 15 '19 at 20:15

c (118 characters) returns a positive value for over-dot-ness and negative value for over-dash-ness

int n(char* c){int v=25124858,d=3541434,i=0,o=0;for(;c[i]!=0;i++)o=(1&(v>(c[i]-65)))>0?(1&(d>>(c[i]-65)))>0?o+1:o-1:o;return o;}


un-golfed

int n(char* c)
{
// Bitwise alpha map:
// more dots = 1
// more dashes or equal = 0
int d=3541434;
// validation bit map.
// dot/dash heavy = 1
// even = 0
int v=25124858;
int i=0,o=0;
for(;c[i]!=0;i++)   // iterate through all values
{
// There is no way to make this pretty
// I did my best.
// If the little endian validation bit corresponding
// to the capitol letter ascii value - 65 = 0,
// the output does not increment or decrement.
// If the value is one it increases or decreases based
// on the value of the d bitmap.
o=(1& ( v > (c[I] - 65))) > 0 ?
(1 & (d >> (c[I] - 65))) > 0 ?
o + 1 :
o - 1 :
o;
}
return o;
}

• I must confess I do not fully understand the comparison 1& ( v > (c[I] - 65)), which is the same as v > c[I] - 65, which I cannot imagine is ever false, so we could remove that whole thing while riffing on @ceilingcat for 56 bytes – gastropner Apr 15 '19 at 16:46

# MathGolf, 22 bytes

{▄="Yⁿ∩┐↑rⁿ¼~<↔"\$▒3-§+


Try it online!

Uses the same method as many other answers, where ⁿ∩┐↑rⁿ¼~<↔" represents the magic number 35344527512513031462452313.

# Python 2, 90 86 bytes

import morse
s=''.join(morse.string_to_morse(input()))
print s.count('.')>s.count('-')


worked on my local with the morse library. -4 bytes. Thanks for the tip @JoKing!

Also, it's 1 byte more if it's in Python 3.

# Python 3, 87 bytes

import morse
s=''.join(morse.string_to_morse(input()))
print(s.count('.')>s.count('-'))


Though the question assumes the number of '.'s and '-'s will not be equal; in case they are equal, this code will return True.

• I mean, you can use input instead of raw_input if you want... – Jo King Mar 14 '19 at 11:34
• @JoKing i tried. It was throwing an error and hence had to resort to raw_input – Koishore Roy Mar 15 '19 at 6:50
• you just have to put quotes around the string, since input` evals STDIN before passing it to the program – Jo King Mar 15 '19 at 7:38
• That is a very fair point. I feel stupid for missing that out! :3 – Koishore Roy Mar 16 '19 at 14:20