24
\$\begingroup\$

On 4chan, a popular game is get. Every post on the site gets a sequential post ID. Since you can't influence or determine them, people try to guess (at least a part of) their own post number, usually the first few digits. Another version of the game is called dubs, and it's goal is to get repeating digits at the end of the number (i.e 1234555).

Your task, if you wish to accept it, is to write a program that takes a post id as input (standard integer, you can assume below 2^32), and returns how many repeating digits are on the end.

Rules

  • Standard loopholes are disallowed.
  • The program can be a function, full program, REPL command, whatever works, really, as long as no external uncounted code/arguments are needed to run it.
  • Input can come from STDIN, function arguments, command line argument, file, whatever suits you.

Test Cases

Input: 14892093
Output: 1

Input: 12344444
Output: 5

Input: 112311
Output: 2

Input: 888888
Output: 6

Input: 135866667 //Post number I got on /pol/ few days ago, rip
Output: 1
\$\endgroup\$
  • 1
    \$\begingroup\$ Are we allowed to take input as string? \$\endgroup\$ – Dead Possum Mar 28 '17 at 9:11
  • 6
    \$\begingroup\$ @DeadPossum I would assume that's allowed, since you get a string anyway if you read the input from STDIN, command-line argument or file (which are all admissible input methods). \$\endgroup\$ – Martin Ender Mar 28 '17 at 9:19
  • 1
    \$\begingroup\$ Can we assume that the input will be greater than 0? \$\endgroup\$ – Martin Ender Mar 28 '17 at 10:01
  • 1
    \$\begingroup\$ @MartinEnder Yes \$\endgroup\$ – sagiksp Mar 28 '17 at 10:05
  • 2
    \$\begingroup\$ Upvote for the dubs game! Check'em! \$\endgroup\$ – ZombieChowder Mar 28 '17 at 12:31

47 Answers 47

19
\$\begingroup\$

Mathematica, 29 bytes

How about an arithmetic solution?

IntegerExponent[9#+#~Mod~10]&

I'm very pleased to see that this beats the straight-forward Mathematica approach.

Explanation

The code itself computes 9*n + n%10 and then finds the largest power of 10 that divides the input, or in other words, counts the trailing zeros. We need to show if n ends in k repeated digits, that 9*n + n%10 has k trailing zeros.

Rep-digits are most easily expressed mathematically by dividing a number like 99999 (which is 105-1) by 9 and then multiplying by the repeated digit. So we can write n = m*10k + d*(10k-1)/9, where m ≢ d (mod 10), to ensure that n doesn't end in more than k repeated digits. Note that d = n%10.

Let's plug that into our formula 9*n + n%10. We get 9*m*10k + d*(10k-1) + d. The d at the end is cancelled, so we're left with: 9*m*10k + d*10k = (9*m + d)*10k. But 9 ≡ -1 (mod 10), so 9*m + d ≡ d - m (mod 10). But we've asserted that m ≢ d (mod 10) and hence d - m ≢ 0 (mod 10).

In other words, we've shown that 9*m + d is not divisible by 10 and therefore, the largest power of 10 that divides 9*n + n%10 = (9*m + d)*10k is k, the number of trailing repeated digits.

As a bonus, this solution prints the correct result, , for input 0.

\$\endgroup\$
  • 1
    \$\begingroup\$ It's times like this that I wish this site supported MathJax; bold formulae are not as nice as typeset ones. It's nice that you took the time to write the exponents superscript though. \$\endgroup\$ – wizzwizz4 Mar 30 '17 at 17:49
  • 1
    \$\begingroup\$ @wizzwizz4 I used to use code formatting, but I've found that bold (which is usually used by Dennis) is a bit more readable than that. But agreed, it's not as nice as MathJax. \$\endgroup\$ – Martin Ender Mar 30 '17 at 17:57
13
\$\begingroup\$

Retina, 9 bytes

&`(.)\1*$

Try it online!

Counts the number of overlapping matches of (.)\1*$ which is a regex that matches a suffix of identical characters.

\$\endgroup\$
  • 2
    \$\begingroup\$ This must be a meme: you and your regex \$\endgroup\$ – Christopher Mar 28 '17 at 10:13
  • \$\begingroup\$ I need to learn all of these modifiers - I would have just gone for (.)(?=\1*$). \$\endgroup\$ – Neil Mar 28 '17 at 11:56
  • 1
    \$\begingroup\$ @DownChristopher he literally made a regex-based language, this goes beyond meme material c: \$\endgroup\$ – Rod Mar 28 '17 at 12:00
  • 1
    \$\begingroup\$ @Neil If it's any consolation, my first attempt was (?=(.)\1*$) (so basically the same as yours). \$\endgroup\$ – Martin Ender Mar 28 '17 at 12:07
  • 1
    \$\begingroup\$ Yes it is, thanks! \$\endgroup\$ – Neil Mar 28 '17 at 12:18
9
\$\begingroup\$

Brachylog, 4 bytes

ẹḅtl

Try it online!

Explanation

ẹ       Elements: split to a list of digits
 ḅ      Blocks: group consecutive equal digits into lists
  t     Tail: take the last list
   l    Length: Output is the length of that last list

If worked directly on integers (and I'm not sure why I didn't implement it so that it does), this would only be 3 bytes as the would not be needed.

\$\endgroup\$
9
\$\begingroup\$

Python 2, 47 41 bytes

lambda s:len(`s`)-len(`s`.rstrip(`s%10`))

Try it online!

36 bytes - For a more flexible input

lambda s:len(s)-len(s.rstrip(s[-1]))

Try it online!

\$\endgroup\$
  • \$\begingroup\$ Wow. I gotta learn builtins more attentively. +1 \$\endgroup\$ – Dead Possum Mar 28 '17 at 12:48
  • 2
    \$\begingroup\$ @DeadPossum dir(object) is our friend c: \$\endgroup\$ – Rod Mar 28 '17 at 12:50
  • \$\begingroup\$ BTW we are not allowed to take string as input. "If your method of input automatically returns strings then sure, but you cannot assume that the input will be provided as strings." :C \$\endgroup\$ – Dead Possum Mar 28 '17 at 13:00
  • 1
    \$\begingroup\$ @DeadPossum I think that the author changed his mind about that. The comment seems to have been deleted. \$\endgroup\$ – Brian McCutchon Mar 29 '17 at 3:15
8
\$\begingroup\$

Javascript (ES6), 55 52 32 30 bytes

a=>a.match`(.)\\1*$`[0].length
  • Saved 19 bytes thanks to @MartinEnder by replacing the regex
  • Saved 2 bytes thanks to @user81655 using tagged templates literals

Using a regex to match the last group of the last digit

Note: First time posting. Do not hesitate to make remarks.

f=a=>a.match`(.)\\1*$`[0].length


console.log(f("14892093"));//1
console.log(f("12344444"));//5
console.log(f("112311"));//2
console.log(f("888888"));//6
console.log(f("135866667 "));//1
\$\endgroup\$
  • \$\begingroup\$ Welcome to PPCG! You can save a lot of bytes by using a backreference instead of filling in the repeated character manually: /(.)\1*$/ \$\endgroup\$ – Martin Ender Mar 28 '17 at 10:02
  • \$\begingroup\$ Also, unnamed functions are completely fine (unless you need the name for recursive calls for example), so you can save two bytes on the f=. \$\endgroup\$ – Martin Ender Mar 28 '17 at 10:03
  • \$\begingroup\$ Good job! This for sure passes review but this could be golfed \$\endgroup\$ – Christopher Mar 28 '17 at 10:07
  • \$\begingroup\$ @MartinEnder Thanks ! I still have to learn how to golf \$\endgroup\$ – Weedoze Mar 28 '17 at 10:13
  • \$\begingroup\$ @DownChristopher Thanks ! I will try to do better next time \$\endgroup\$ – Weedoze Mar 28 '17 at 10:13
7
\$\begingroup\$

C, 62 56 48 47 bytes

Saved a byte thanks to @Steadybox!

j,k;f(n){for(k=j=n%10;j==n%10;n/=10,k++);k-=j;}

Try it online!

\$\endgroup\$
7
\$\begingroup\$

PHP, 47 45 40 bytes

while($argn[-++$i]==$argn[-1]);echo$i-1;

Run with echo <n> | php -nR '<code>

seems a loop is still smaller than my first answer. simply count the chars that are equal to the last. This uses negative string offsets of PHP 7.1.

-5 bytes by Titus. Thanks !


Old answer:

<?=strlen($a=$argv[1])-strlen(chop($a,$a[-1]));

removes from the right every character matching the rightmost character and calculates the difference in the length.

\$\endgroup\$
  • \$\begingroup\$ -R and $argn could save 5 bytes. \$\endgroup\$ – Titus Mar 30 '17 at 8:58
6
\$\begingroup\$

05AB1E, 4 bytes

.¡¤g

Try it online! or as a Test suite

Explanation

.¡    # group consecutive equal elements in input
  ¤   # get the last group
   g  # push its length
\$\endgroup\$
6
\$\begingroup\$

CJam, 7 bytes

re`W=0=

Try it online!

Explanation

r   e# Read input.
e`  e# Run-length encode.
W=  e# Get last run.
0=  e# Get length.
\$\endgroup\$
6
\$\begingroup\$

Jelly, 5 bytes

DŒgṪL

Try it online!

Explanation

D      # convert from integer to decimal   
 Œg    # group runs of equal elements
   Ṫ   # tail
    L  # length
\$\endgroup\$
6
\$\begingroup\$

Perl 5, 22 bytes

21 bytes of code + -p flag.

/(.)\1*$/;$_=length$&

Try it online!

/(.)\1*$/ gets the last identical numbers, and then $_=length$& assigns its length to $_, which is implicitly printed thanks to -p flag.

\$\endgroup\$
6
\$\begingroup\$

C (gcc), 32 29 bytes

f(x){x=x%100%11?1:-~f(x/10);}

This is a port of my Python answer.

This work with gcc, but the lack of a return statement is undefined behavior.

Try it online!

\$\endgroup\$
  • \$\begingroup\$ I'm confused, how come you neither pass a pointer, and change the value at the location, or just return the value. This looks like it just changes the local copy, which would make the function unusable, but this works on TIO. You also add 1 to n in the footer, rather then sizeof(int), wouldn't that move it 1 byte forwards, rather than the full width of an int? Clearly there are some tricks I could learn here, and I could probably use the first one in my own answer. \$\endgroup\$ – Bijan Mar 29 '17 at 0:01
  • 2
    \$\begingroup\$ All the return statement does is storing the return value in EAX. With gcc, assigning it to a variable happens to do the same thing. As for the pointer arithmetic, when you add 1 to an int pointer, it moves to the next int, not the next byte. \$\endgroup\$ – Dennis Mar 29 '17 at 3:54
  • \$\begingroup\$ Are there cases (when using ints) when it would be better to return, it seems like in the worst case you would make a new int, and assign that. \$\endgroup\$ – Bijan Mar 29 '17 at 12:40
  • \$\begingroup\$ @Bijan C compilers always align direct memory access to the size of an atom of the primitive in question -- i don't remember if it's in the standard, though \$\endgroup\$ – cat Mar 29 '17 at 13:00
5
\$\begingroup\$

Python 2, 51 bytes

Takes integer as input. Try it online

lambda S:[x==`S`[-1]for x in`S`[::-1]+'~'].index(0)

48 bytes for string as input. Try it online

lambda S:[x==S[-1]for x in S[::-1]+'~'].index(0)
\$\endgroup\$
5
\$\begingroup\$

C#, 63 62 bytes


Golfed

i=>{int a=i.Length-1,b=a;while(a-->0&&i[a]==i[b]);return b-a;}

Ungolfed

i => {
    int a = i.Length - 1,
        b = a;

    while( a-- > 0 && i[ a ] == i[ b ] );

    return b - a;
}

Ungolfed readable

i => {
    int a = i.Length - 1, // Store the length of the input
        b = a ;           // Get the position of the last char

    // Cycle through the string from the right to the left
    //   while the current char is equal to the last char
    while( a-- > 0 && i[ a ] == i[ b ] );

    // Return the difference between the last position
    //   and the last occurrence of the same char
    return b - a;
}

Full code

using System;

namespace Namespace {
   class Program {
      static void Main( String[] args ) {
         Func<String, Int32> f = i => {
            int a = i.Length - 1, b = a;
            while( a-- > 0 && i[ a ] == i[ b ] );
            return b - a;
         };

         List<String>
            testCases = new List<String>() {
               "14892093",
               "12344444",
               "112311",
               "888888",
               "135866667"
            };

         foreach( String testCase in testCases ) {
            Console.WriteLine( $" Input: {testCase}\nOutput: {f( testCase )}\n" );
         }

         Console.ReadLine();
      }
   }
}

Releases

  • v1.1 - - 1 byte  - Thanks to Kevin's comment.
  • v1.0 -  63 bytes - Initial solution.

Notes

Nothing to add

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

Python 2, 38 32 bytes

f=lambda n:0<n%100%11or-~f(n/10)

Thanks to @xnor for saving 6 bytes!

Try it online!

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

MATL, 6 5 bytes

1 byte saved thanks to @Luis

&Y'O)

Try it at MATL Online

Explanation

        % Implicitly grab input as a string
&Y'     % Perform run-length encoding on the string but keep only the second output
        % Which is the number of successive times an element appeared
O)      % Grab the last element from this array
        % Implicitly display
\$\endgroup\$
  • \$\begingroup\$ I had forgotten that & did that to Y':-D Why not take input as a string enclosed in quotes and get rid of j? \$\endgroup\$ – Luis Mendo Mar 28 '17 at 14:07
  • \$\begingroup\$ @LuisMendo I wasn't sure if I could do that since the challenge explicitly said that input was an "integer" \$\endgroup\$ – Suever Mar 28 '17 at 14:17
  • \$\begingroup\$ I assumed so from Martin's comment and from the default rules, which allow that. But I'm not really sure \$\endgroup\$ – Luis Mendo Mar 28 '17 at 14:18
  • \$\begingroup\$ @LuisMendo Ah ok didn't see his comment. Will update! \$\endgroup\$ – Suever Mar 28 '17 at 14:20
4
\$\begingroup\$

Cubix, 24 19 bytes

)uO)ABq-!wpUp)W.@;;

Note

  • Actually counts how many of the same characters are at the end of the input, so this works for really big integers and really long strings as well (as long as the amount of same characters at the end is smaller than the maximum precision of JavaScript (around 15 digits in base-10).
  • Input goes in the input field, output is printed to the output field

Try it here

Explanation

First, let's expand the cube

    ) u
    O )
A B q - ! w p U
p ) W . @ ; ; .
    . .
    . .

The steps in the execution can be split up in three phases:

  1. Parse input
  2. Compare characters
  3. Print result

Phase 1: Input

The first two characters that are executed are A and B. A reads all input and pushes it as character codes to the stack. Note that this is done in reverse, the first character ends up on top of the stack, the last character almost at the bottom. At the very bottom, -1 (EOF) is placed, which will be used as a counter for the amount of consecutive characters at the end of the string. Since we need the top of the stack to contain the last two characters, we reverse the stack, before entering the loop. Note that the top part of the stack now looks like: ..., C[n-1], C[n], -1.

The IP's place on the cube is where the E is, and it's pointing right. All instructions that have not yet been executed, were replaced by no-ops (full stops).

    . .
    . .
A B E . . . . .
. . . . . . . .
    . .
    . .

Phase 2: Character comparison

The stack is ..., C[a-1], C[a], counter, where counter is the counter to increment when the two characters to check (C[a] and C[a-1]) are equal. The IP first enters this loop at the S character, moving right. The E character is the position where the IP will end up (pointing right) when C[a] and C[a-1] do not have the same value, which means that subtracting C[a] from C[a-1] does not yield 0, in which case the instruction following the ! will be skipped (which is a w).

    . .
    . .
. S q - ! w E .
p ) W . . ; ; .
    . .
    . .

Here are the instructions that are executed during a full loop:

q-!;;p) # Explanation
q       # Push counter to the bottom of the stack
        #     Stack (counter, ..., C[a-1], C[a])
 -      # Subtract C[a] from C[a-1], which is 0 if both are equal
        #     Stack (counter, ..., C[a-1], C[a], C[a-1]-C[a])
  !     # Leave the loop if C[a-1]-C[a] does not equal 0
   ;;   # Remove result of subtraction and C[a] from stack
        #     Stack (counter, ..., C[a-1])
     p  # Move the bottom of the stack to the top
        #     Stack (..., C[a-1], counter)
      ) # Increment the counter
        #     Stack (..., C[a-1], counter + 1)

And then it loops around.

Phase 3: Print result

Since we left the loop early, the stack looks like this: counter, ..., C[a-1]-C[a]. It's easy to print the counter, but we have to increment the counter once because we didn't do it in the last iteration of the loop, and once more because we started counting at -1 instead of 0. The path on the cube looks like this, starting at S, pointing right. The two no-ops that are executed by the IP are replaced by arrows that point in the direction of the IP.

    ) u
    O )
. B . . . S p U
. ) . . @ . . .
    > >
    . .

The instructions are executed in the following order. Note that the B) instructions at the end change the stack, but don't affect the program, since we are about to terminate it, and we do not use the stack anymore.

p))OB)@ # Explanation
p       # Pull the counter to the top
        #     Stack: (..., counter)
 ))     # Add two
        #     Stack: (..., counter + 2)
   O    # Output as number
    B)  # Reverse the stack and increment the top
      @ # End the program

Alea iacta est.

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

Batch, 91 bytes

@set s=-%1
@set n=1
:l
@if %s:~-2,1%==%s:~-1% set s=%s:~,-1%&set/an+=1&goto l
@echo %n%

The - prevents the test from running off the start of the string.

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

JavaScript (ES6), 34 bytes

f=(n,p)=>n%10-p?0:1+f(n/10|0,n%10)

Not shorter than the regex solution.

Recursive function which evaluates the digits from right-to-left, stopping when a different digit is encountered. The result is the number of iterations. p is undefined on the first iteration, which means n%10-p returns NaN (falsy). After that, p equals the previous digit with n%10. When the current digit (n%10) and the previous (p) are different, the loop ends.

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

Röda, 12 bytes

{count|tail}

Try it online!

This is an anonymous function that expects that each character of the input string is pushed to the stream (I think this is valid in spirit of a recent meta question).

It uses two builtins: count and tail:

  1. count reads values from the stream and pushes the number of consecutive elements to the stream.
  2. tail returns the last value in the stream.
\$\endgroup\$
3
\$\begingroup\$

T-SQL, 238 214 Bytes

declare @ varchar(max) = '' declare @i int=0, @e int=0, @n int=right(@,1), @m int while (@i<=len(@)) begin set @m=(substring(@,len(@)-@i,1)) if (@n=@m) set @e=@e+1 else if (@i=0) set @e=1 set @i=@i+1 end select @e

Or:

declare @ varchar(max) = '12345678999999'
declare 
    @i int = 0,
    @e int = 0,
    @n int = right(@,1),
    @m int

while (@i <= len(@))
begin
    set @m = (substring(@,len(@)-@i,1))
    if (@n = @m) set @e = @e + 1
    else
    if (@i) = 0 set @e = 1
    set @i = @i + 1
end
select @e
\$\endgroup\$
2
\$\begingroup\$

Java 7, 78 bytes

int c(int n){return(""+n).length()-(""+n).replaceAll("(.)\\1*$","").length();}

Try it here.

I tried some things using recursion or a loop, but both ended up above 100 bytes..

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

Powershell, 41 Bytes

for($n="$args";$n[-1]-eq$n[-++$a]){};$a-1

straightforward loop backwards until a char doesn't match the last char in the string, return the index of that char -1.

-3 thanks to @AdmBorkBork - using a for loop instead of a while.

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

Mathematica, 33 30 bytes

Thanks to Greg Martin for saving 3 bytes.

Tr[1^Last@Split@Characters@#]&

Takes input as a string.

Gets the decimal digits (in the form of characters), splits them into runs of identical elements, gets the last run and computes the length with the standard trick of taking the sum of the vector 1^list.

\$\endgroup\$
  • \$\begingroup\$ Characters instead of IntegerDigits? \$\endgroup\$ – Greg Martin Mar 28 '17 at 17:23
  • \$\begingroup\$ @GregMartin Ah yeah, I guess. Thanks. \$\endgroup\$ – Martin Ender Mar 28 '17 at 17:24
  • \$\begingroup\$ You still don't beat that other shrewd Mathematica golfer for this question ;) \$\endgroup\$ – Greg Martin Mar 28 '17 at 17:26
  • \$\begingroup\$ @GregMartin What a shame. :) \$\endgroup\$ – Martin Ender Mar 28 '17 at 17:27
2
\$\begingroup\$

Bash + Unix utilities, 34 bytes

sed s/.*[^${1: -1}].//<<<x$1|wc -c

Try it online!

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

JavaScript (ES6), 39 38 37 27 bytes

f=n=>n%100%11?1:1+f(n/10|0)

Maybe not shorter than the regex-based solution, but I couldn't resist writing a solution entirely based on arithmetic. The technique is to repeatedly take n % 100 % 11 and divide by 10 until the result is non-zero, then count the iterations. This works because if the last two digits are the same, n % 100 % 11 will be 0.

\$\endgroup\$
  • \$\begingroup\$ Ah, you finished just before me haha! I'm not sure whether to post another answer, since they will most likely converge after golfing, but here's my solution using 34 bytes: f=(n,p)=>n%10-p?0:1+f(n/10|0,n%10) \$\endgroup\$ – user81655 Mar 28 '17 at 13:44
  • \$\begingroup\$ @user81655 That's great, feel free to post it. I don't think mine will converge down to that without a complete makeover, and of course now that I've seen yours that won't happen ;-) \$\endgroup\$ – ETHproductions Mar 28 '17 at 13:51
2
\$\begingroup\$

Haskell, 33 bytes

f(h:t)=sum[1|all(==h)t]+f t
f _=0

Try it online!

Takes string input. Repeatedly cuts off the first character, and adds 1 if all characters in the suffix are equal to the first one.

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

R, 35 bytes

rle(rev(charToRaw(scan(,''))))$l[1]

Brief explanation

                  scan(,'')         # get input as a string
        charToRaw(         )        # convert to a vector of raws (splits the string)
    rev(                    )       # reverse the vector
rle(                         )$l[1] # the first length from run length encoding
\$\endgroup\$
2
\$\begingroup\$

Befunge-98, 19 bytes

01g3j@.$~:01p-!j$1+

Try it online!

This could be made shorter if I managed to only use the stack.

How it works:

01g3j@.$~:01p-!j$1+
01g                 ; Get the stored value (default: 32)                 ;
   3j               ; Skip to the ~                                      ;
        ~           ; Get the next character of input                    ;
         :01p       ; Overwrite the stored value with the new char       ;
             -!     ; Compare the old value and the new                  ;
               j$   ; Skip the $ when equal, else pop the counter        ;
                 1+ ; Increment the counter                              ;

; When the input runs out, ~ reflects the IP and we run: ;
   @.$
     $              ; Pop the extraneous value (the stored value) ;
   @.               ; Print the number and exit                   ;
\$\endgroup\$
2
\$\begingroup\$

Python 3 - 50 44 bytes

Full program (in Python 3, input() returns a string, no matter the input):

g=input();print(len(g)-len(g.rstrip(g[-1]))) 
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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