# Numbers vs. Strings: Language fitness challenge

inspired by thejonymyster's idea

## Rules

This challenge is about finding languages that are very suitable for one task but quite the opposite in the other. The two tasks share a theme, but Task 1 is designed to be number-oriented while 2 is string-oriented. You can participate in three categories:

• Numbers: Choose a language, and solve both tasks in it. The language must be specified down to a specific implementation, version, and flags, and these cannot be changed once posted. Each solution is scored by the code size in bytes; your answer's score is $$\{T_2}/{T_1}$/extract_tex] where $$\T_1\$$ is the score for Task 1 and $$\T_2\$$ is for Task 2. Higher score is better. • Strings: Same as Numbers, except for scoring. Your answer's score is $$\{T_1}/{T_2}\$$, i.e. the reciprocal of that of Numbers. Higher score is better. • Robbers: Choose an answer X for Numbers or Strings. Come up with a better solution for the worse task for the given language, and post it as a comment. By doing this, you gain (effectively steal) X's score lost. Higher total score is better. • Example: Let's assume a Numbers post with 4B in task 1 and 9B in task 2. If you golf task 2 down to 7B, the answer's score is reduced from 9/4 to 7/4, and you get 2/4 = 0.5 points. You will naturally participate in Numbers if your solution to Task 2 is longer than Task 1, and in Strings otherwise. However, you may not switch the category of an answer already posted, even if the golfing attempts result in the score less than 1. Everyone is free to give golfing suggestions to existing answers, but the only ones that reduce the answer's score count as robbers. Once the challenge is inactive for 1 week, the winners of each category will be decided as follows: • Numbers and Strings: the highest scoring answer in each category wins. • Robbers: the participant with the highest total stolen score wins. ## Task 1: Number thickness Given a positive integer $$\n\$$ and integer base $$\b \ge 2\$$, compute the thickness of $$\n\$$ in base $$\b\$$. For base 2, the values are A274036. The thickness is computed as follows: if the inputs are $$\n = 22\$$ and $$\b = 2\$$, • Convert $$\n\$$ to base-$$\b\$$ digits: $$\10110_2\$$ • Treat it as a polynomial: $$\B_n(x) = 1x^4 + 0x^3 + 1x^2 + 1x^1 + 0x^0\$$ • Compute its square: $$\B_n(x)^2 = x^8 + 2x^6 + 2x^5 + x^4 + 2x^3 + x^2\$$ • Take the highest coefficient: 2. Therefore, the thickness of 22 in base 2 is 2. Test cases 22, 2 -> 2 8, 2 -> 1 15, 2 -> 4 100, 3 -> 6 12345, 10 -> 46  ## Task 2: String thickness Given a nonempty string $$\s\$$ consisting of uppercase letters, compute the string thickness of $$\s\$$. It is calculated as follows: if the input is ABAAB, • For each length-2 substring of $$\s\$$, replace all non-overlapping appearances of it with $$\s\$$. • AB -> ABAAB: ABAABAABAAB • BA -> ABAAB: AABAABAABAABAABAABAB • AA -> ABAAB: ABAABBABAABBABAABBABAABBABAABBABAABBAB • AB -> ABAAB: ABAABAABAABBABAABAABAABBABAABAABAABBABAABAABAABBABAABAABAABBABAABAABAABBABAAB • Count how many times $$\s\$$ appears as non-overlapping substrings of the result. ABAABAABAABBABAABAABAABBABAABAABAABBABAABAABAABBABAABAABAABBABAABAABAABBABAAB 11111 22222 33333 44444 55555 66666 77777 88888 99999 aaaaa bbbbb ccccc ddddd  The string thickness of ABAAB is 13. For this task, taking the input string as a list of chars or a list of codepoints is allowed. Test cases ABAAB -> 13 AB -> 1 XXYY -> 2 ARRAY -> 3 NUMBER -> 5 PQRRQP -> 6 XYXZYX -> 21  ## Example submission # Numbers, Python 3.10, score 109 / 54 = 2.0185 ## Task 1, 54 bytes <insert code here><insert code here><insert code here> ## Task 2, 109 bytes <insert code here><insert code here><insert code here> <insert code here><insert code here><insert code here>  • @Steffan Tagging as code-golf would imply that the winning criterion is "shortest code wins". Sep 20 at 0:40 • I don't have the time to attempt it now, but a sed strings answer could be a strong contender. Sep 20 at 3:06 • This challenge made me realize a lot of (golfing) languages lack a replace builtin.. :/ Sep 20 at 10:36 • Could we get some test cases? Sep 20 at 23:01 ## 11 Answers # Strings, Python 3.8.10, score 83 / 65 = 1.2769 ## Task 1, 83 bytes -7 bytes from @xnor (+7/65) lambda n,b:max(sum(n//b**i%b*(n*b**i//b**k%b)for i in range(n))for k in range(n+1))  Attempt this Online! ## Task 2, 65 bytes -1 byte from @Steffan s=t=p=input() for c in s:t=t.replace(p+c,s);p=c print(t.count(s))  Attempt This Online! • Replace t=t.replace(p+(p:=c),s) with t=t.replace(p+c,s);p=c for -1 byte / -0.02097 score Sep 20 at 2:47 • @Steffan I think you mean +0.02097 score, right? Sep 20 at 3:37 • Yes. (filler) (filler) Sep 20 at 3:52 • It's much more boring, but I think this works for 84 bytes on task 1. – xnor Sep 20 at 4:22 • 83 bytes with a small tweak – xnor Sep 20 at 4:40 # Numbers, Factor 0.99 Build #1889 + math.extras math.polynomials, score 66 / 53 = 1.2453 ## Task 1, 53 bytes [ '[ [ _ /mod , ] until-zero ] f make 2 p^ supremum ]  Attempt This Online! ## Task 2, 66 bytes [| s | s s s 2 clump [ <regexp> s re-replace ] each count-subseq ]  Attempt This Online! I didn't expect Factor to score particularly well here since it's pretty consistent in most areas. Now if it were iterative vs. recursive, you might see Factor reigning supreme... P.S. I was able to knock 12 bytes off one of the answers after posting, so FML. # Numbers, PARI/GP 2.13.4, score 77 / 37 = 2.0811 ## Task 1, 37 bytes n->b->vecmax(Vec(Pol(digits(n,b))^2))  Attempt This Online! PARI/GP has a built-in polynomial type. ## Task 2, 77 bytes s->u=strjoin;v=strsplit;for(i=2,#t=s,t=u(v(t,u(Vec(s)[i-1..i])),s));#v(t,s)-1  Attempt This Online! PARI/GP has only two string-manipulation built-ins: strjoin and strsplit. We can do string search-and-replace by strjoin(strsplit(s,a),b). # Strings, 05AB1E, score 15/9 = 1.666... ## Task 1, 15 bytes вDδ*εā_«NFÁ]øOà  Try it online. ## Task 2, 9 bytes ü2I.:I¡g<  Try it online. 05AB1E lacks any polynomial builtins, and unfortunately also a matrix-diagonals builtin. So all things considering, the Numbers Task 1 isn't too long, if I say so myself. No doubt someone still finds something to golf, since that's usually the case with my answers. ;) # Numbers, Mathematica 13.1.0, score 1.26315 1.47826 +0.2151 score thanks to att! ## Task 1, 57 46 bytes Max@ListConvolve[#,#,{1,-1},0]&@*IntegerDigits  Try it online! -11 bytes thanks to att ## Task 2, 72 68 bytes Fold[StringReplace,x=#,#->x&/@StringPartition[x,2,1]]~StringCount~x&  Try it online! -4 bytes thanks to att • -5 bytes task 1 (→ 1.56522) and -4 bytes task 2 (-0.08696 → 1.47826) – att Sep 20 at 4:16 • Oops, forgot to change: -11, not -5 on task 1. The -5 used O to get the coefficient list. – att Sep 20 at 5:16 # Numbers, Vyxal 2.17.1, score 9/8 = 1.125 Vyxal doesn't do very well for this challenge. ## Task 1, 8 bytes τ:v*ÞḋṠG  Try it Online! ## Task 2, 9 bytes 2l(n?V)O  Try it Online! • Vyxal G? Would make your score 10/7 Sep 23 at 4:20 # Numbers, Jelly, score 13/5 = 2.6 ## Task 1, 5 bytes bæcṀ  Try it online! ## Task 2, 13 bytes ṡ2œṣj³ɗƒœṣ¹L’  Try it online! It's common knowledge that Jelly is not good with strings, but this is exceptionally awkward for its builtin set with some chaining issues on top. Maybe I'll get robbed? # Numbers, J 806, Score 48 / 23 = 2.08696 ## Task 1, 23 bytes [:>./[:+//.@:(*/)~#.inv  Try it online! ## Task 2, 48 bytes #%~;&''(]-&#rplc~)[:;<rplc~&.>/@|.@,<<"1@,.~2<$


Try it online!

Strings might have an open window or two for an enterprising robber...

• Quick -2 bytes for Task 2: avoid division by replacing with (;}.) instead of ;&''. Sep 20 at 5:38
• Thanks bubbler.... So, do I change it or am I being robbed? Sep 20 at 14:58

# Strings, Go 1.19.1, score 177 / 162 = 1.09259 176 / 121 = 1.41322

## Task 1: 177 176 bytes

func n(n,b int)int{c,m:=[]int{},-1
for n>0{c=append(c,n%b)
n/=b}
s:=make([]int,len(c)*2)
for i,x:=range c{for j,y:=range c{s[i+j]+=x*y}}
for _,n:=range s{if m<n{m=n}}
return m}


Attempt This Online!

• -1 by @Steffan

## Task 2: 162 121 bytes

import."strings"
func s(s string)int{p,t:=s,s
for _,c:=range s{q:=string(c);t=ReplaceAll(t,p+q,s);p=q}
return Count(t,s)}


Attempt This Online!

• -41 by @Steffan
• 121 for the second one Sep 22 at 18:47
• for the first one, you can remove the newline after func n(n,b int)int{ Sep 22 at 18:51

# Numbers, Charcoal, score 23 / 19 = 1.21

ＮθＮηＩ⌈↨Ｘ↨↨θη×θη²×θη


Try it online! Link is to verbose version of code. Explanation: Based on @dingledooper's Python answer but using Charcoal's base conversion builtins to simplify the process.

ＳηＦＥΦθκ⁺§θκι≔⪫⪪ηιθηＩ№ηθ


Try it online! Link is to verbose version of code. Explanation: Charcoal struggles to extract overlapping substrings, and like PARI/GP, has to use both Split and Join to perform string replacement. It does at least have a convenient way to refer to the same string input twice.

# Numbers, Pyxplot 0.8.4, score 188/99 = 1.8990

su N(n,b){m=0
fo j=0ton{s=0
fo i=0ton{f='floor(n/b*'
s=s+@f*i)%b*@f*j*b**i)%b
}
m=max(m,s)
}
pr m
}


The algorithm is the same as in @dingledooper's answer.

su S(s){t=s
L='strlen'
r='strrange'
fo i=2to@L(s){j=0
c=0
while j<@L(t){if strcmp(@r(t,j,j+2),@r(s,i-2,i)){j=j+1
}else{t='%s%s%s'%(@r(t,0,j),s,@r(t,j+2,@L(t)));j=j+@L(s);c=c+1
}
}
}
pr c
}


Pyxplot has a search-and-replace operator (=~) but it only works with literal text and so is not of use here. There are only five string manipulation functions (two of which perform case conversions). The three used here are strcmp, which performs lexicographical comparison; strlen, which returns the length; and strrange, which returns a slice.

There is no online interpreter. To install Pyxplot 0.8.4 on an up-to-date system, you need to add -fgnu89-inline to the compile flags in line 44 of Makefile.skel. You might also need to change python to python2 or python2.X` in lines 97, 180, and 183.