14
\$\begingroup\$

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 :)

\$\endgroup\$
16
  • \$\begingroup\$ Since this can by computed by a "generate everything and find the input" strategy, a harder variation might allow inputs to be arbitrarily large, and guarantee only that you are given enough digits to uniquely find it, assuming the input is the first instance of that sequence in the nats. \$\endgroup\$
    – Jonah
    Commented Dec 8, 2023 at 7:01
  • \$\begingroup\$ @Jonah Good call. After all, the "find input in string" strategy is probably how I'd do it. Do you think it's too late to change with an update given the 7 answers, or is it worth improving now? Not sure of Code Golf conventions. \$\endgroup\$ Commented Dec 8, 2023 at 12:18
  • 1
    \$\begingroup\$ @LukeSawczak I think it would need to be a part 2 post \$\endgroup\$
    – Jonah
    Commented Dec 8, 2023 at 15:36
  • 1
    \$\begingroup\$ @P.b I don't follow. If we're dealing with consecutive natural numbers from 1 to 1,000, the only valid sequence I see is ...(4)56,457,458,4(59)... Here's how I reason: we can't be in the single digits, because 4,6 isn't valid. We can't be in the double digits, because neither 56,45 nor 64,57 is valid. So we must be in the triple digits. It can't be 564,574 or 645,745, so it must be 457,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 of 10 up to the column value... \$\endgroup\$ Commented Dec 8, 2023 at 22:14
  • 1
    \$\begingroup\$ I missed on the 1 to 1000 part and got mislead by the example being larger than 1000 in the first place. \$\endgroup\$
    – P.b
    Commented Dec 9, 2023 at 11:53

17 Answers 17

6
\$\begingroup\$

Excel (ms365)

1) Recursion with LAMBDA(), 74 bytes:

enter image description here

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".

\$\endgroup\$
5
\$\begingroup\$

05AB1E, 7 bytes

LJIkIg+

Times out for larger inputs. Add a leading (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)
\$\endgroup\$
5
\$\begingroup\$

Vyxal, 50 bitsv2, 6.25 bytes

⌊ɾṅḟ?L+

Try it Online!

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.

\$\endgroup\$
3
  • \$\begingroup\$ It’s a little misleading for the link in the header to go to the default branch, since this is Vyxal 2 \$\endgroup\$ Commented 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\$
    – lyxal
    Commented 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\$ Commented Dec 9, 2023 at 2:29
5
\$\begingroup\$

JavaScript (Node.js), 43 bytes

x=>~(g=s=>~s.indexOf(x,1)||g(s+i++))(x,i=1)

Try it online!

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

Try it online!

-4 from Arnauld

Not using the 10

\$\endgroup\$
4
  • \$\begingroup\$ 53 bytes? \$\endgroup\$
    – Arnauld
    Commented Dec 8, 2023 at 7:46
  • \$\begingroup\$ @Arnauld Is this correct? \$\endgroup\$
    – l4m2
    Commented Dec 8, 2023 at 7:59
  • \$\begingroup\$ Yes, that looks safe. \$\endgroup\$
    – Arnauld
    Commented Dec 8, 2023 at 8:22
  • \$\begingroup\$ How does this work? Does it also use brute force, like most other answers? \$\endgroup\$ Commented Dec 20, 2023 at 15:22
5
\$\begingroup\$

Ruby, 34 30 bytes

->i{[*1..1e3]*''=~/(?<=#{i})/}

Try it online!

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.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ I don't think you need the + do you? \$\endgroup\$
    – Neil
    Commented Dec 9, 2023 at 14:42
  • \$\begingroup\$ @Neil well.. thank you! \$\endgroup\$
    – AZTECCO
    Commented Dec 9, 2023 at 16:28
4
\$\begingroup\$

Perl 5 (-p), 27 bytes

(join"",1..1e3)=~$_;$_="@+"

Try it online!

\$\endgroup\$
4
\$\begingroup\$

Haskell, 65 63 bytes

-2 bytes thanks to @AZTECCO

n%h|l<-length n,n==take l h=l
n%(_:h)=1+n%h
f=(%([1..]>>=show))

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ 63 \$\endgroup\$
    – AZTECCO
    Commented Dec 8, 2023 at 13:54
3
\$\begingroup\$

Retina 0.8.2, 38 bytes

^
1001$*1¶
\G1
$.`
r`\B\1.*¶(.*)
$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`\B\1.*¶(.*)
$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`\B\1.*¶(.*)
$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`\B\1.*¶(.*)
$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.

\$\endgroup\$
3
\$\begingroup\$

Pip, 10 bytes

Semi-port of lyxal's Vyxal answer

J1,a~:Xa$)

Attempt This Online!

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.

\$\endgroup\$
2
  • \$\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 the X as well.) \$\endgroup\$
    – DLosc
    Commented Mar 6 at 7:12
  • \$\begingroup\$ @DLosc new version?? :D I’ll update my answers later this month, I can’t right now \$\endgroup\$
    – math scat
    Commented Mar 6 at 7:53
3
\$\begingroup\$

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
\$\endgroup\$
3
\$\begingroup\$

APL+WIN, 35 33 bytes

Two bytes saved thanks to Tbw

Prompts for string of digits:

↑(¯1+⍴s)+((s←,⎕)⍷n)/⍳⍴n←⊃,/⍕¨⍳1E3

Try it online! Thanks to Dyalog Classic

\$\endgroup\$
2
  • \$\begingroup\$ You can save bytes with ⊃,/⍕¨⍳1E3 to make the string. \$\endgroup\$
    – Tbw
    Commented Dec 8, 2023 at 16:27
  • \$\begingroup\$ @Tbw Thanks. Edited code. \$\endgroup\$
    – Graham
    Commented Dec 8, 2023 at 17:31
2
\$\begingroup\$

APL (Dyalog Classic), 22 bytes

≢-1-(⊃∘⍸⍷∘(⊃,/⍕¨⍳1E3))

Try it online!

≢-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.

\$\endgroup\$
2
\$\begingroup\$

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.

\$\endgroup\$
1
\$\begingroup\$

Japt, 9 bytes

+A³õ ¬
aN

Try it

\$\endgroup\$
0
\$\begingroup\$

JavaScript (Node.js), 57 bytes

x=>[...Array(1000).keys()].join('').indexOf(x)-1+x.length

Attempt This Online!

Constructs "0123456789...", then finds the input in it.

\$\endgroup\$
0
\$\begingroup\$

Scala 3, 41 bytes

s=>(1 to 1000).mkString.indexOf(s)+s.size

Attempt This Online!

\$\endgroup\$
0
\$\begingroup\$

Uiua, 30 bytes

(⊏0+⧻:⊚⌕:/$"__"+1⇡1e3.|0;)=0⧻.

Test suite

I felt like adding another answer

\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.