# Funny Numbers :D

The task is to calculate the average "funniness" of a given number given the following scoring system:

• 1 point for each "420" in it
• 2 points for each "69" in it
• 3 points if its a palindrome (doesn't count if it's just a single digit)
• 4 points if it has (not for each) "800813"
• 5 points for ending in "420"
• 6 points for ending in "69"

Then, divide that total score by the number of digits in the number (round to the nearest tenth)

Test Cases:

• 96942024969: 1.3 (14p/11 digits, 1p for one "420", 4p for two "69"s, 3p since its an palindome, 6p for ending in "69")

• 800813800813: 0.3 (4p/12 digits for having "800813")

• 0: 0 (0p/1 digit)

• 420: 2 (6p/3 digits, 1p for one "420", 5p for ending in "420")

• 2435083240587: 0 (0p/13 digits)

Answers are ranked by lowest program size.

• Welcome to CGCC! This question seems not to have an objective scoring criterion. Are we trying to minimize program size, or something else? Sep 27 at 19:38
• You say 8008135 gives +4, but then in the test cases it's 800813. Which one is correct? Sep 27 at 19:44
• Could you clarify what you mean by a number being an anagram? Sep 27 at 19:48
• You mean palindrome not anagram, I think Sep 27 at 19:55
• So... The funniest number would be 69? (6+2)/2= 4 in funny scale :P Sep 28 at 9:01

# 05AB1E, 35 bytes

Ž¥ú2ä©¢IÂQIg≠*I•CΘ=•åI®Å¿)˜ā*OIg/1.ò


Explanation:

Ž¥ú2ä©¢    # Verify the first two rules:
Ž¥ú        #  Push compressed integer 42069
2ä      #  Split it into two parts: [420,69]
©     #  Store it in variable ® (without popping)
¢    #  Count how many times each occur in the (implicit) input-string
IÂQIg≠*    # Verify the third rule:
I          #  Push the input again
Â         #  Bifurcate it; short for Duplicate & Reverse copy
Q        #  Pop both and check if they're the same (aka it's a palindrome)
Ig      #  Push the input-length
≠     #  Check that it's NOT 1 (0 if 1; 1 if >=2)
*    #  Multiply them together
I•CΘ=•å    # Verify the fourth rule:
I          #  Push the input again
•CΘ=•     #  Push compressed integer 800813
å    #  Check if the input contains this number as substring
I®Å¿       # Verify the fifth and sixth rules:
I          #  Push the input yet again
®         #  Push pair [420,69] from variable ®
Å¿       #  Check whether the input ends with either of these two
)          # Wrap all items on the stack into a list
˜         # Flatten the list of pairs and loose values to a single list
ƶ        # Multiply each value in the list by its 1-based index
O       # Then sum the list together
Ig/    # Divide it by the input-length
1.ò # Round it to 1 decimal after the period
# (after which the result is output implicitly)


See this 05AB1E tip of mine (section How to compress large integers?) to understand why Ž¥ú is 42069 and •CΘ=• is 800813.

# Raku, 89 bytes

{round (m:g/420/+2*m:g/69/+3*($_>9&&$_
eq.flip)+4*?/800813/+5*?/420$/+6*?/69$/)/.comb,.1}


Try it online!

Regex-driven, conveniently.

# Excel, 188 bytes

=LET(
a,800813,
b,{69,420},
c,A1,
d,LEN(c),
ROUND(
SUM(
MMULT(d-LEN(SUBSTITUTE(c,b,"")),1/{1;3}),
3*(d>1)*(c=0+CONCAT(MID(c,d-SEQUENCE(d)+1,1))),
4*(FIND(a,c&a)<d),
(0+RIGHT(c,{2,3})=b)*{6,5}
)/d,
1
)
)


Input in cell A1.

# Vyxal, 302 bitsv2, 37.75 bytes

⁺md69"₌vøEvO?₍λḂ⁼n₀>*;‡800813c$WfÞż∑$L/1∆W


Try it Online!

Many more bytes added to handle single digits not being a palindrome.

• -1 bit Sep 28 at 3:56

# Python, 136 131 bytes

-5 from @Jonathan Allan

lambda s:"%0.1f"%(((c:=s.count)(m:="420")+2*c("69")+3*(s[:1]<s*c(s[::-1]))+4*("800813"in s)+5*(e:=s.endswith)(m)+6*e("69"))/len(s))


Attempt This Online!

A crappy solution, but a solution nonetheless.

• Save three by counting occurrences of the reverse with 1<len(s)*c(s[::-1]). Save another with m:="420". Sep 27 at 22:34
• Actually, one more with s[:1]<s*c(s[::-1]) instead. Sep 27 at 23:34

# JavaScript (ES11), 136 bytes

s=>~~([/420/g,/69/g,,800813,/420$/,/69$/].reduce((t,r,i)=>t-~i/3*~~s.match(r)?.length,s>9&[...s].reverse().join==s)*30/s.length+.5)/10


Attempt This Online!

• – l4m2
Sep 28 at 1:15

# Charcoal, 5756 55 bytes

﹪%.1f∕⁺⁺ΣＥ⪪42069³⁺×⁺⁵κ¬⊟⪪θι×⊕κ№θι∧∧⊖Ｌθ⁼θ⮌θ³∧№θ800813⁴Ｌθ


Try it online! Link is to verbose version of code. Explanation:

         Ｅ⪪42069³                                         Map over 420,69
×⁺⁵κ¬⊟⪪θι                               5 or 6 if ends with
⁺                                        Plus
×⊕κ№θι                         1 or 2 times count
∧∧⊖Ｌθ⁼θ⮌θ³               3 if palindrome
∧№θ800813⁴     4 if 800813
⁺⁺Σ                                                 Take the sum
Ｌθ     Divide by length
﹪%.1f                                                       Round to 0.1
Implicitly print


Previous 57 56 byte solution:

﹪%.1f∕ΣＥ⟦№θ420№θ69∧⊖Ｌθ⁼θ⮌θ‹⁰№θ800813¬⊟⪪θ420¬⊟⪪θ69⟧×ι⊕κＬθ


Try it online! Link is to verbose version of code. Explanation:

         №θ420                                              Count of 420s
№θ69                                          Count of 69s
∧⊖Ｌθ⁼θ⮌θ                                  Is a palindrome
‹⁰№θ800813                        Includes 800813
¬⊟⪪θ420                 Ends with 420
¬⊟⪪θ69           Ends with 69
Ｅ⟦                                        ⟧          Map over values
×ι⊕κ      Multiply by index
Σ                                                     Take the sum
∕                                                Ｌθ    Divide by length
﹪%.1f                                                       Round to 0.1
Implicitly print


# APL(Dyalog Unicode), 65 bytes SBCS

1⍕≢÷⍨1⊥4⍸⍤⌽(1<≢×⊢≡⌽),(1∊'800813'⍷,),(,⍤⍉⍤↑'024' '96'(⊃,+/)⍤⍷¨⊂⍤⌽)


Try it on APLgolf!

# JavaScript (Node.js), 123 bytes

n=>([s=.5,/420/g,/69/g,n>9&&[...n].reverse().join,800813,/420$/,/69$/].map((x,i)=>n.replace(x,y=>s+=i*10/n.length))|s)/10


Try it online!

# Retina 0.8.2, 205201 197 bytes

(?=(.*?420)*)(?=(.*?69)*)(?=((.)+.?(?<-4>\4)+$(?(4)^))?)(?=(.*800813)?).+(?<=(420)?)(?<=(69)?)$#1$*1$#2$*2$#3$*3$#5$*4$#6$*5$#7$*6/$.&$* \d$*
\G1
10$* /(.+)\1$1$& r.*(\3)*(\3{10})*/(1+)$#2.$#1  Try it online! Link includes test cases. Explanation: (?=(.*?420)*)(?=(.*?69)*)(?=((.)+.?(?<-4>\4)+$(?(4)^))?)(?=(.*800813)?).+(?<=(420)?)(?<=(69)?)
$#1$*1$#2$*2$#3$*3$#5$*4$#6$*5$#7$*6/$.&$*


Work out how many times 420 and 69 appear, plus also record whether the input is a nontrivial palindrome, whether it contains 800813, and whether it ends with 420 or 69, plus take its length in unary.

\d
$*  Convert the scores to unary individually; the length is unaffected, since it is already in unary. \G1 10$*
/(.+)\1
$1$&
r.*(\3)*(\3{10})*/(1+)
$#2.$#1


Divide the total score by the length, rounding to the nearest 0.1, and converting to decimal.

# Ruby, 114 112 bytes

->n{b=0;[/420/,/69/,n?n.reverse: ?a,/(800813.*)+/,/420$/,/69$/].sum{|x|n.scan(x).size*b+=1.0/n.size}.round 1}


Try it online!

# Scala, 289 bytes

Port of @97.100.97.109's Python answer in Scala.

Thanks to @Joseph's help to correct the scala code.

Golfed version. Try it online!

s=>BigDecimal((s.sliding(3).count(_=="420")+2*s.sliding(2).count(_=="69")+3*(if(s==s.reverse&s.length>1)1 else 0)+(if(s.contains("800813")) 4 else 0)+5*(if(s.endsWith("420"))1 else 0)+6*(if(s.endsWith("69"))1 else 0)).toDouble/s.length).setScale(1,BigDecimal.RoundingMode.HALF_UP).toDouble


Ungolfed version. Try it online!

object Main extends App {

def calculateScore(s: String): Double = {
val count420 = s.sliding(3).count(_ == "420")
val count69 = s.sliding(2).count(_ == "69")
val palindromeBonus = if (s == s.reverse && s.length > 1) 1 else 0
val count800813 = if(s.contains("800813")) 4 else 0  // Adjusted to just check if "800813" exists in the string
val end420Bonus = if (s.endsWith("420")) 1 else 0
val end69Bonus = if (s.endsWith("69")) 1 else 0

val totalScore = count420 + 2 * count69 + 3 * palindromeBonus + count800813 + 5 * end420Bonus + 6 * end69Bonus

BigDecimal(totalScore.toDouble / s.length).setScale(1, BigDecimal.RoundingMode.HALF_UP).toDouble
}

override def main(args: Array[String]): Unit = {
val inputs = List("96942024969", "800813800813", "0", "420", "2435083240587")
for (i <- inputs) {
println(s"$i :${calculateScore(i)}")
}
}
}

• 800813800813 fails because the "800813" bonus isnt for each instance, only for having an instance, sorry for the trick lol ;) Oct 4 at 23:15
• @Joseph Thanks a lot, I have corrected it. Oct 4 at 23:42