# Rockstar Poetic Number Literals!

The Rockstar programming language has "poetic number literals", allowing you to assign nonnegative, finite (at least one Rockstar interpreter supports infinity) numbers to variables without typing a single digit: just type words with length equal to each digit, modulo 10. For example,

This is a challenge


sets the variable this to 19.

So here is the challenge: given a string as input, output its value as a poetic number literal.

To calculate the value, split the string up into words (separated by one or more spaces, one or more commas, or both), then take the ones digit of the length of each word, and finally concatenate for the value. However, if there are one or more periods ., the first period is to be interpreted as a decimal point, and any other periods treated as word separators.

You can assume the input is nonempty, and will consist of nothing but letters, commas, periods and spaces. Also, you can assume there is no period before the first word.

You can ignore edge cases, like when the word is not supposed to be interpreted as a number. For example,

The news is true


will not set the variable the news to 4, because true is to be interpreted as a boolean value. However, your program should output 4 given true as an input.

Test cases:

test cases -> 45
hi -> 2
hi      bye -> 23
hi , ,, ,,, bye -> 23
hi , ,, .,,, bye -> 2.3
hi, bye -> 23
hi,bye -> 23
verylongword -> 2
a verylongword -> 12
this is azerodigit -> 420
azerodigit -> 0
azerodigit.four -> 0.4
one.azerodigit one -> 3.03
azerodigit hi -> 2
hi. bye -> 2.3
hi.bye -> 2.3
hi. -> 2
hi. bye azerodigit -> 2.3
hi. bye azerodigit ha -> 2.302
hi. azerodigit -> 2
hi.bye.ha -> 2.32
hi.,,..,bye.,.,.,.,.,ha -> 2.32
hi,,..,bye.,.,.,.,.,ha -> 2.32
hi,,,bye.,.,.,.,.,ha -> 23.2
hi,,,bye,,,,,ha -> 232


This is , so fewest bytes wins!

Edit: For clarity, there cannot be trailing 0s in the decimal part, or leading 0s in the integer part of the number for valid inputs. For example, azerodigit hi. azerodigit should output 2, not 02.0, 2.0 or anything other than 2.

• Is it guaranteed that the input contains at most one period, and that the period will always be followed by a space and another word? Commented Mar 29 at 20:46
• Can you be more specific about “ignoring commas”? For example, can the input be foo,bar and if so how would it be interpreted? Commented Mar 29 at 21:02
• hi,bye -> 33 should be 23, no? Commented Mar 30 at 8:08
• Is it possible for there to be a period before the first word? Commented Mar 30 at 20:55
• Looks like you've got some test cases in there multiple times. Also, the second to last test case has a comma after it. Commented Mar 31 at 11:11

# JavaScript (ES6), 68 bytes

s=>+s.replace(/(?<!\..*)(\.)|\w+|(.)/g,(a,b,c)=>c?"":b||a.length%10)


Try it online!

# JavaScript (Node.js), 61 bytes

s=>+s.replace(/\w+|./g,a=>a+d<1?d=a:a>'?'?a.length%10:"",d=1)


Try it online!

-2B from tsh

You can assume the input is nonempty, and will consist of nothing but letters, commas, periods and spaces.

With letter filtered, all cases can be listed as follow:

d comma period space
1 ,1 .1  1
'.' ,. ..  .

Only .1 is smaller than 1

• Note that assumption is needed, as if b=='-' then b+1<1 is also true
– l4m2
Commented Mar 30 at 11:37
• s=>+s.replace(/\w+|./g,a=>a+d<1?d=a:a>{}?a.length%10:"",d=1)
– tsh
Commented Apr 1 at 5:07
• @tsh Is it promised that all are lowercase?
– l4m2
Commented Apr 1 at 5:24

# Retina 0.8.2, 66 bytes

((\.)|.)*?(?=\w)(\w{10})*(\w*)
$2$.4
1>\.

^0+\B|\.?0*(?<=\..*)$ Try it online! Link includes test cases. Explanation: Skips over enough non-letters to reach the next word, then skips over multiples of 10 letters, then counts any remaining letters, and captures any ., outputting the number of remaining letters and any captured .. Edit: Added an extra stage to remove insignificant zeros that don't change the value of the result. Edit: Improved the detection of .s and added an extra stage to remove .s after the first. • Your answer is invalid, see my latest edit. There cannot be trailing 0s in the decimal part, or leading 0s in the integer part of the number for valid inputs (so azerodigit hi should output 2 instead of 02) Commented Mar 29 at 22:31 • @JonathanAllan Actually that's just a bug, it doesn't handle multiples of 10 correctly. – Neil Commented Mar 31 at 20:18 # JavaScript (ES6), 93 bytes s=>s.split(/\W+/).map(w=>++a&&w.length%10,a=0).join/10**(a-s.match(/(?<!\..*)\w+/g).length)  Try it online! Borrows the JS test runner from Arnauld's answer. Getting back into CodeGolf after a long time, tried a different approach than Arnauld's beautiful regex magic. # UiuaSBCS, 32 31 bytes ⋕▽⬚0⍜⊡¬⊗@.,≥@0.⍜⊜□(°⋕◿10∵◇⧻)⌵±.  Try it! -1 thanks to noodle man! ⋕▽⬚0⍜⊡¬⊗@.,≥@0.⍜⊜□(°⋕◿10∵◇⧻)⌵±.­⁡​‎⁪⁪⁠⁪⁪⁠⁪⁪⁠⁪⁪⁠⁪⁪⁠⁪⁪⁠⁪⁪⁠⁪⁪⁠⁪⁪⁠⁪⁪⁠⁪⁪⁠⁪⁪⁠⁪⁪⁠‎⁪⁡⁪⁠⁪⁢⁤⁤⁪‏‏​⁡⁠⁡‌⁢​‎⁪⁪⁠⁪⁪⁠⁪⁪⁠⁪⁪⁠⁪⁪⁠‎⁪⁡⁪⁠⁪⁢⁤⁡⁪‏⁠‎⁪⁡⁪⁠⁪⁢⁤⁢⁪‏⁠‎⁪⁡⁪⁠⁪⁢⁤⁣⁪‏‏​⁡⁠⁡‌⁣​‎‎⁪⁡⁪⁠⁪⁤⁤⁪‏⁠‎⁪⁡⁪⁠⁪⁢⁡⁡⁪‏⁠‎⁪⁡⁪⁠⁪⁢⁡⁢⁪‏⁠‎⁪⁡⁪⁠⁪⁢⁡⁣⁪‏⁠‎⁪⁡⁪⁠⁪⁢⁣⁤⁪‏‏​⁡⁠⁡‌⁤​‎‎⁪⁡⁪⁠⁪⁢⁣⁡⁪‏⁠‎⁪⁡⁪⁠⁪⁢⁣⁢⁪‏⁠‎⁪⁡⁪⁠⁪⁢⁣⁣⁪‏‏​⁡⁠⁡‌⁢⁡​‎‎⁪⁡⁪⁠⁪⁢⁢⁢⁪‏⁠‎⁪⁡⁪⁠⁪⁢⁢⁣⁪‏⁠‎⁪⁡⁪⁠⁪⁢⁢⁤⁪‏‏​⁡⁠⁡‌⁢⁢​‎⁪⁪⁠‎⁪⁡⁪⁠⁪⁢⁡⁤⁪‏⁠‎⁪⁡⁪⁠⁪⁢⁢⁡⁪‏‏​⁡⁠⁡‌⁢⁣​‎‎⁪⁡⁪⁠⁪⁤⁣⁪‏‏​⁡⁠⁡‌⁢⁤​‎⁪⁪⁠‎⁪⁡⁪⁠⁪⁣⁤⁪‏⁠‎⁪⁡⁪⁠⁪⁤⁡⁪‏⁠‎⁪⁡⁪⁠⁪⁤⁢⁪‏‏​⁡⁠⁡‌⁣⁡​‎‎⁪⁡⁪⁠⁪⁢⁤⁪‏⁠‎⁪⁡⁪⁠⁪⁣⁡⁪‏⁠‎⁪⁡⁪⁠⁪⁣⁢⁪‏⁠‎⁪⁡⁪⁠⁪⁣⁣⁪‏‏​⁡⁠⁡‌⁣⁢​‎‎⁪⁡⁪⁠⁪⁢⁡⁪‏⁠‎⁪⁡⁪⁠⁪⁢⁢⁪‏⁠‎⁪⁡⁪⁠⁪⁢⁣⁪‏‏​⁡⁠⁡‌⁣⁣​‎‎⁪⁡⁪⁠⁪⁣⁪‏⁠‎⁪⁡⁪⁠⁪⁤⁪‏‏​⁡⁠⁡‌⁣⁤​‎‎⁪⁡⁪⁠⁪⁢⁪‏⁠⁪⁪‏​⁡⁠⁡‌⁤⁡​‎‎⁪⁡⁪⁠⁪⁡⁪‏‏​⁡⁠⁡‌­ . # ‎⁡duplicate ⌵± # ‎⁢mask of letters ⍜⊜□( ) # ‎⁣apply function to each contiguous mask group ∵◇⧻ # ‎⁤lengths ◿10 # ‎⁢⁡modulo ten °⋕ # ‎⁢⁢unparse . # ‎⁢⁣duplicate ≥@0 # ‎⁢⁤mask of digits ⊗@., # ‎⁣⁡index of first period ⍜⊡¬ # ‎⁣⁢negate at index ⬚0 # ‎⁣⁣filling with zero if no period found ▽ # ‎⁣⁤keep characters given mask ⋕ # ‎⁤⁡parse to number, removing leading and trailing zeros 💎  Created with the help of Luminespire. • <0± can be ⌵± Commented Mar 30 at 12:42 # Charcoal, 36 bytes ≔⪪Ｓ.θＩＩ⪫Ｅ⟦§θ⁰⪫Φθκ ⟧⭆Φ⪪⪫⪪ι,¦ ¦ λ﹪Ｌλχ.  Try it online! Link is to verbose version of code. Explanation: ≔⪪Ｓ.θ  Split the input on all .s. (Charcoal doesn't have an easy way to split on just the first ..) ＩＩ⪫Ｅ⟦§θ⁰⪫Φθκ ⟧⭆Φ⪪⪫⪪ι,¦ ¦ λ﹪Ｌλχ.  For the first part and the join of any remaining parts on spaces, replace commas with spaces, then split on spaces, remove empty words, and replace the words with their lengths modulo 10. Join the pieces together with a ., then cast to float and back to string to remove irrelevant zeros. # Jelly, 26 bytes ”.ɓœṡnŒs$Œg§ḟ€0%⁵Ḍœrƭ€0j⁹t


A full program that accepts a string and prints the Rockstar poetic number literal.

Try it online! Or see the test-suite.

#### How?

”.ɓœṡnŒs$Œg§ḟ€0%⁵Ḍœrƭ€0j⁹t - Main Link: list of characters, Poem ”.ɓ - start a new chain f(Poem, Dot='.') œṡ - split Poem at the first Dot nŒs$                  - not equal swapped-case? (vectorises)
Œg                - group runs of equal elements
(only vectorises  at depth 1)
§               - sums
ḟ€0            - filter zeros from each
%⁵          - mod ten
€     - for each:
ƭ      -   alternate between:
Ḍ         -     1) convert from decimal
-> integer part as an integer
œr  0    -     2) trim zeros from right
-> decimal part as a digit list
j⁹  - join with a Dot
t - trim any Dots from either side
(removes a potential trailing dot)
- implicit, smashing print


# Regex, 97 bytes (RegRep)

Not very short, but I thought it was funny.

[A-z]/_
\b_|0_/1
1_/2
2_/3
3_/4
4_/5
5_/6
6_/7
7_/8
8_/9
9_/0
^0(?=\d)|(?<=\..*)(\.|0$)|\.$|[, ]


Commented:

[A-z]/_     Replace all chars with _ to make counting shorter
\b_|0_/1    Replace all starting _ with 1
(\b|0)_ is longer lol
1_/2        1 -> 2
2_/3        2 -> 3
3_/4        3 -> 4, etc.
4_/5        .
5_/6        .
6_/7        .
7_/8        .
8_/9        .
9_/0        .
^0(?=\d)|(?<=\..*)(\.|0$)|\.$|[, ] removes...
|         |        |  |   |   | extra chars
|         |        |  |   | trailing decimal
|         |        |  | trailing 0...
|         |        | or any period...
|         | but only after the first decimal point


# Swift 5.9, 154 bytes

let f={let s=($0+"").split{$0=="."}
return Float({[""+s[0],{s[1...].joined}()(" ")].map{$0.split{$0<"."}.map{"\($0.count%10)"}.joined()}.joined}()("."))!}  TIO is too old, so here's a JDoodle link instead (with test cases). This is, at its core, a similar idea to @Neil's Charcoal answer, just a lot more verbose. # Perl 5-p, 55 bytes s/\w+/(length$&)%10/ge;s/\./!$a++&&'.'/ge;y/, //d;$_+=0


Try it online!

# 05AB1E, 31 30 bytes

'.©1.;1¡ε1ú.γa}ιθεgθ]J®ý1/0Ü®Ü


Explanation:

'.                 '# Push "."
©                 # Store it in variable ® (without popping)
1.;              # Replace the first "." in the (implicit) input with a 1
1¡            # Then split on that 1
ε           # Map over both parts:
.γ }       # Adjacent group by:
a        #  Is alphabetic?
ι      # Uninterleave into two parts
θ     # Only keep the last part with the words
ε    # Map over the words:
g   # Pop and push its length
θ  # Pop and keep its last digit (aka mod-10)
]           # Close the nested maps
J          # Join each inner-most lists of digits together
®ý        # Join both parts back together with a "."-delimiter
1/                  # Divide it by 1 to remove trailing/leading 0s (which also
# adds a ".0" to any integers)
0Ü                # Remove the trailing 0
®Ü              # Remove the trailing "."
# (after which the result is output implicitly as result)


=let(f,lambda(i,join(,sort(mod(len(split(index(split(substitute(substitute(A1,".","µ",1),".",","),"µ"),,i)," ,",1,1)),10)))),--(f(1)&iferror("."&f(2))))


Put the input in cell A1 and the formula in cell B1.

Ungolfed:

=let(
parts, split(substitute(substitute(A1, ".", "µ", 1), ".", ","), "µ"),
get_, lambda(i, join("", index(mod(len(split(index(parts,,i), " ,", 1, 1)), 10)))),
value(get_(1) & iferror("." & get_(2)))
)
`