Someone I know has no coding experience, but has proposed an algorithm* to determine the character limit of text fields they find online. They copy a string containing the numbers from 1 to 1,000 inclusive, not separated in any way, and they read the last few digits it displays.
For example, after pasting, they might see
...5645745845
From here, they can figure out the character limit.
They've got two problems with this approach. One, it's a little hard to determine where the discrete numbers are in the string. (The last whole number displayed here is 458, and the final two digits would have been followed by 9 if the text field allowed one more character.)
Two, the math is a little tricky even when that character has been identified. It's easy with single digits. For instance, if the last whole number were 5, the limit would be 5 characters. With double digits it's a little harder. If the last whole number were 13 followed by the 1 of 14, the full field would display 123456789101112131 for a limit of 18 characters.
They've managed to get a script that copies the last 10 digits the text field displays, or as many as the field holds if the field can hold less than 10. They'd like to feed that into another script that returns the field's length limit.
Additional test cases:
'' -> 0
'1' -> 1
'12' -> 2
'7891011121' -> 16
'1191201211' -> 256
'5645745845' -> 1268
Here are some examples of invalid inputs, incidentally:
'0'
'121'
'1211'
* Possibly in jest :)
17 Answers 17
Excel (ms365)
1) Recursion with LAMBDA(), 74 bytes:
Formula in B1:
=LET(x,LAMBDA(y,n,s,IFERROR(FIND(A1,s),y(y,n+1,s&n))),x(x,1,""))+LEN(A1)-1
Note: Due to the limitations within Excel this may return an error above a certain amount of recursive lambda calls.
2) Concatenating with ROW(), 39 bytes:
I did explicitly want to stay away from using a concatenated string from any arbitrary range of numbers for this challenge. If one is okay with this concept then try:
=FIND(A1,CONCAT(ROW(1:8468)))+LEN(A1)-1
Here I found that concatenating ROW(1:8468) seems to be Excel's (or rather CONCAT()'s) limit.
3) Overcome Excel's limits using PY(), 87 bytes:
To overcome these limits of function within Excel, we could use the new PY() function:
=PY(
''.join(map(str,range(1,int(xl("A1")+1)))).find(str(xl("A1")))++len(str(xl("A1")))
)
Note: Python is not my forté, so I'm sure this can be golfed down. However, more importantly. Since PY() is executed on an external server there is a high chance of this code error out due to a "time-limit".
05AB1E, 7 bytes
LJIkIg+
Times out for larger inputs. Add a leading 4 (push 1000) to speed it up.
Try it online or verify all test cases.
Explanation:
L # Push a list in the range [1, (implicit) input-integer]
J # Join it together to a single string
Ik # Pop and push the (0-based) index of the input
Ig+ # Add the length of the input
# (after which the result is output implicitly)
Vyxal, 50 bitsv2 , 6.25 bytes
⌊ɾṅḟ?L+
Bitstring:
11001011010011010000000111000101111000110100000010
Times out for very large inputs because it needs to generate a range between 1 and whatever number represented by the input.
Explained
⌊ɾṅḟ?L+
⌊ɾ # The range [1, input]
ṅ # Joined into a single string.
ḟ # Find the index of the input in that string
?L+ # And add the length of the input to that
💎
Created with the help of Luminespire.
-
\$\begingroup\$ It’s a little misleading for the link in the header to go to the default branch, since this is Vyxal 2 \$\endgroup\$noodle person– noodle person2023年12月08日 17:02:37 +00:00Commented Dec 8, 2023 at 17:02
-
\$\begingroup\$ @noodleman never attribute to malice what can adequately be explained by stupidity (ie forgetting to update the template generator) \$\endgroup\$2023年12月08日 21:35:18 +00:00Commented Dec 8, 2023 at 21:35
-
1\$\begingroup\$ never attribute to malice what can adequately be explained by stupidity (ie using the word "misleading" instead of "confusing") :p \$\endgroup\$noodle person– noodle person2023年12月09日 02:29:58 +00:00Commented Dec 9, 2023 at 2:29
JavaScript (Node.js), 43 bytes
x=>~(g=s=>~s.indexOf(x,1)||g(s+i++))(x,i=1)
Using range, fail 11 (expect 13, get 1)
JavaScript (Node.js), 49 bytes
x=>~(g=s=>~s.search(x)||g(s+ ++i))(i='')+x.length
-4 from Arnauld
Not using the 10
-
-
-
\$\begingroup\$ Yes, that looks safe. \$\endgroup\$Arnauld– Arnauld2023年12月08日 08:22:30 +00:00Commented Dec 8, 2023 at 8:22
-
\$\begingroup\$ How does this work? Does it also use brute force, like most other answers? \$\endgroup\$Fabian Röling– Fabian Röling2023年12月20日 15:22:22 +00:00Commented Dec 20, 2023 at 15:22
Ruby, (削除) 34 (削除ここまで) 30 bytes
->i{[*1..1e3]*''=~/(?<=#{i})/}
Thanks to @Neil for saving 1 Byte by removing useless + in regexp
Regexp /(?<=#{i})+/ finds index next to input in the constructed string [*1..1e3]*'' by using a look behind.
Retina 0.8.2, 38 bytes
^
1001$*1¶
\G1
$.`
r`\B1円.*¶(.*)
1ドル
\B
Try it online! Link includes test cases. Explanation:
^
1001$*1¶
\G1
$.`
Create a string of all the numbers from 0 to 1000 concatenated.
r`\B1円.*¶(.*)
1ドル
Remove everything after the first copy of the input, but don't delete the leading 0. The r reverses the direction of processing, so the (.*) is matched first and the \B last.
\B
Count the pairs of adjacent digits, which is the same as the length excluding the leading 0.
Alternative 38-byte version that works for arbitrary numbers given enough memory and processing power but is slower for inputs of four or more digits.
^
$'$*111¶
\G1
$.`
r`\B1円.*¶(.*)
1ドル
\B
Try it online! Link includes test cases. Explanation:
^
$'$*111¶
\G1
$.`
Create a string of all the numbers from 0 to the input plus 1 concatenated. (This is needed for the edge case of an empty input.)
r`\B1円.*¶(.*)
1ドル
Remove everything after the first copy of the input, but don't delete the leading 0.
\B
Take the length excluding the leading 0.
Pip, 10 bytes
Semi-port of lyxal's Vyxal answer
J1,a~:Xa$)
J1,a~:Xa$)
J1,a # Range from 1 to input as string
~:Xa # Match input as regex in range
$) # Return last index of first match
💎
Created with the help of Luminespire.
-
\$\begingroup\$ If you switch the operands to
~, you can get rid of the:. (In the upcoming version 1.2, you'll be able to drop theXas well.) \$\endgroup\$DLosc– DLosc2024年03月06日 07:12:26 +00:00Commented Mar 6, 2024 at 7:12 -
\$\begingroup\$ @DLosc new version?? :D I’ll update my answers later this month, I can’t right now \$\endgroup\$math scat– math scat2024年03月06日 07:53:55 +00:00Commented Mar 6, 2024 at 7:53
Charcoal, 10 bytes
I+Lθ⌕⭆φ⊕ιθ
Try it online! Link is to verbose version of code. Explanation:
φ Predefined variable `1000`
⭆ Map over implicit range and join
ι Current value
⊕ Incremented
⌕ Find index of
θ Input string
+ Plus
θ Input string
L Length
I Cast to string
Implicitly print
APL+WIN, (削除) 35 (削除ここまで) 33 bytes
Two bytes saved thanks to Tbw
Prompts for string of digits:
↑( ̄1+⍴s)+((s←,⎕)⍷n)/⍳⍴n←⊃,/⍕ ̈⍳1E3
APL (Dyalog Classic), 22 bytes
≢-1-(⊃∘⍸⍷∘(⊃,/⍕ ̈⍳1E3))
≢-1-(⊃∘⍸⍷∘(⊃,/⍕ ̈⍳1E3)) # tacit function
⊃∘⍸⍷∘ # index of first subsequence equal to input in
1E3 # 1000
⍳ # range
⍕ ̈ # toString each
,/ # concat reduce
⊃,/⍕ ̈⍳1E3 # '12345678910...'
-1- # minus 1 (because a-1-c = a-(1-c) = ̄1+a+c in APL)
≢ # length of input (this is one character;
💎 # the code block does not display it correctly)
Created with the help of Luminespire.
Python 3, 55 bytes
lambda s:"".join(map(str,range(1,1001))).find(s)+len(s)
This is a rather simple solution, but it works.
JavaScript (Node.js), 57 bytes
x=>[...Array(1000).keys()].join('').indexOf(x)-1+x.length
Constructs "0123456789...", then finds the input in it.
...(4)56,457,458,4(59)...Here's how I reason: we can't be in the single digits, because4,6isn't valid. We can't be in the double digits, because neither56,45nor64,57is valid. So we must be in the triple digits. It can't be564,574or645,745, so it must be457,458. However, that does give me an interesting idea for a variation of the problem: rather than knowing the numbers are consecutive, the step could be any power of10up to the column value... \$\endgroup\$