Is it a pleasing number?

22

3

A pleasing number (according to this definition) is a number that can be passed through the following process (let's use 41802000 as an example):

  • Separate the trailing identical numbers (41802000 => [41802, 000])
  • Sort the first half of the digits and take the maximum ([41802, 000] => [8, 000])
  • Take the length of the final element. Call the resultant elements A and B ([8, 000] => A=8, B=3)
  • Is NB = A for any integer N? (True in this example; 23 = 8)

If the input results in True from the following process, it is considered pleasing.

Your task is to take an integer x, and output whether x is a pleasing number. You can output any two distinct values for truthy and falsey, but please state what you're using in your answer. x is guaranteed to have at least two distinct digits (e.g. 111 is an invalid input). As with most challenges, you may take x as a string, or a list of digits.

This is a so shortest code in bytes wins.

Test cases

          Input          Output
       41802000               1
            100               1
      123456788               0
      451111111               0
234543454545444               0
             12               1
       41902000               0
          92599               1

caird coinheringaahing

Posted 2017-12-17T20:31:20.083

Reputation: 13 702

can the number be passed as a string? (especially given the '234543454545444' test case) – Uriel – 2017-12-17T21:08:33.133

@Uriel You may take input as a string – caird coinheringaahing – 2017-12-17T21:10:09.577

3As a suggestion for clarification: I would use the term "digit" rather than "number", as you are specifically referring to the decimal characters, abstracted from their number values. – Jonathan Frech – 2017-12-17T22:43:16.250

list of digits - would this be a list of the ASCII numeral characters, or a list of integers from 0-9 – Οurous – 2017-12-17T23:05:42.293

1@Οurous Up to you – caird coinheringaahing – 2017-12-17T23:08:12.340

Would 1 be considered a pleasing number? (01) 0 is 0^1. – fəˈnɛtɪk – 2017-12-18T00:40:17.880

@fəˈnɛtɪk - does not matter since "x is guaranteed to have at least two distinct digits" (although I see your "01" reasoning) – Jonathan Allan – 2017-12-18T00:44:30.697

@DLosc Added, Thanks! – caird coinheringaahing – 2018-04-04T07:09:45.817

Answers

9

APL (Dyalog), 36 bytes

{(⊢≡⌊)(⌈/⍎¨⍵/⍨~o)*÷≢⍵/⍨o←⌽⌊\1,2=/⌽⍵}

Try it online!

How?

Almost a poem.

⌽⍵ - reverse the input once,

1,2=/ - get the differences list.

⌊\ - keep only the first group of ones,

- and flip it over to complete.


o← - assign to o,

~o - switch ones and zero(s),

⍵/⍨ - filter the input with it,

⍎¨ - turn the result into list of each digit,

  • ⌈/ - and get the maximum. (that's A)

⍵/⍨o - filter the input with o unalt(ered),

- and take the length, that would be B.

÷ - get one divided by this result,

* - and take A to that power thee.


⊢≡⌊ - integer?

Uriel

Posted 2017-12-17T20:31:20.083

Reputation: 11 708

8

05AB1E, 11 bytes

γRćgUZXzm.ï

Try it online!

Explanation

γRćgUZXzm.ï ~ Full program.

γ           ~ Split into runs of digits.
 R          ~ Reverse.
  ć         ~ Push a[1:], a[0] to the stack.
   g        ~ Length (of a[0]).
    U       ~ Assign this to the integer variable X.
     ZX     ~ Get the maximum, without popping, and push X.
       zm   ~ A1/B.
         .ï ~ Is it an integer?

Emigna saved 1 byte.

Relies on the fact that if A is a positive integer N raised to the power of B, then N=A1/B, hence it must be an integer.

Mr. Xcoder

Posted 2017-12-17T20:31:20.083

Reputation: 39 774

UZX should work instead of s{θs – Emigna – 2017-12-17T21:07:21.257

The 9-byte program fails for 41902000 (should be falsy). – Zgarb – 2017-12-17T21:18:04.057

@Zgarb Yeah I was nearly sure it would fail, so I removed it... Also lol we got the exact same integer

– Mr. Xcoder – 2017-12-17T21:18:41.393

Fails for 418802000 – Okx – 2018-04-01T12:59:19.343

8

Haskell, 85 75 72 71 bytes

Edit: -10 bytes by taking a list of digits instead of a string. Thanks to WhatToDo for pointing out that this is allowed. -3 bytes thanks to Ourous' solution in Clean. -1 byte thanks to user28667.

f s|(b,a)<-span(==last s)$reverse s=or[n^length b==maximum a|n<-[1..9]]

Try it online! Takes input as a list of digits. Example usage: f [4,1,8,0,2,0,0,0] yields True.

Explanation:

Given an input s=[4,1,8,0,2,0,0,0], we reverse the list and separate the leading elements with span(==last s): ([0,0,0],[2,0,8,1,4]). The pattern matching on (b,a) yields b=[0,0,0] and a=[2,0,8,1,4].

The list comprehension or[n^length b==maximum a|n<-[1..a]] checks whether any integer n in the range from 1 to 9 satisfies n^length b==maximum a, that is n^3=8.

Laikoni

Posted 2017-12-17T20:31:20.083

Reputation: 23 676

You posted yours before I did mine, and ours are similar, so: Try it online!

– WhatToDo – 2017-12-17T22:38:30.807

@WhatToDo Thanks, I didn't see that lists of digits where allowed as input. – Laikoni – 2017-12-17T22:51:33.453

Can’t you just take the maximum. No need to check them all. – Tim – 2017-12-18T11:17:09.470

@Tim I'm not sure I understand what you mean. Taking the maximum of the whole input list to get a would fail in cases like 477. – Laikoni – 2017-12-18T11:36:10.473

@Tim I do take the maximum to get b, but check every integer n from 0 to 9 (formerly from 0 to a). That's exactly the specification as far as I see. – Laikoni – 2017-12-18T11:52:17.140

I think you can replace (reverse s) with $reverse s – user28667 – 2017-12-18T12:43:19.947

@user28667 Thanks, the parenthesis where needed the previous 75 byte version, but now they indeed can be replaced. – Laikoni – 2017-12-18T15:36:59.163

5

Haskell, 104 89 bytes

@Laikoni found a shorter solution, but this is the best I could do. Thanks @Laikoni for letting me know that we can also accept lists of digits as input.

import Data.List
(g.length.last<*>maximum.concat.init).group
g b a=any(==a)$(^b)<$>[1..a]

Explanation:

Try it online!

flawr

Posted 2017-12-17T20:31:20.083

Reputation: 40 560

Why use any(==a) when you could use elem a? – Post Rock Garf Hunter – 2017-12-19T15:40:29.107

@WheatWizard Thanks for the suggestions, regarding your second comment: Wouldn' this fail for e.g. 2888? – flawr – 2017-12-19T15:57:43.267

Yes it seems I misread the question. I didn't realize that the trailing numbers could be anything other than zero. – Post Rock Garf Hunter – 2017-12-19T16:01:02.633

but head.maximum is still shorter than maximum.concat by 2 bytes, and maintains the functionality. – Post Rock Garf Hunter – 2017-12-19T16:01:56.307

4

Jelly, 11 bytes

ŒgµṪL9*€fṀL

Takes input as a list of digits.

Try it online!

How it works

ŒgµṪL9*€fṀL  Main link. Argument: D (digit array)

Œg           Group runs of digits, yielding a run array R.
  µ          Begin a new chain with argument D.
   Ṫ         Tail; remove and yield the last element of D.
    L        Take the length. Let's call it b.
     9*€     Compute [1**b, ..., 9**b].
         Ṁ   Take the maximum run in R, yileding [a, ..., a].
        f    Filter, yielding either [a] (if a = n**b for some n) or [].
          L  Take the length. 

Dennis

Posted 2017-12-17T20:31:20.083

Reputation: 196 637

Before looking at the answers, and without knowing Jelly at all, I guessed that the Jelly answer would be 12 bytes. ;) – DLosc – 2018-04-03T23:15:38.670

4

R, 80 bytes

function(x)any((0:(m=max((d=rle(rev(utf8ToInt(c(x,''))-48)))$v[-1])))^d$l[1]==m)

Try it online!

Uses utf8ToInt - 48 to split the number into digits. This throws a warning from the conversion to a string.

Using rle get the count of the trailing digits and the max value of the first digits. Return true if the any of the range 0 to max value to the power of trailing count equals max value.

I think there are further golfing opportunities, but that can wait until tomorrow.

MickyT

Posted 2017-12-17T20:31:20.083

Reputation: 11 735

2I deleted my answer because I didn't see that my post was just combining your answer and @NofP's: function(x,R=rle(rev(utf8ToInt(x)-48)))!max(R$v[-1])^(1/R$l[‌​1])%%1 (66 bytes, taking x as a string) – plannapus – 2017-12-18T12:25:58.063

@plannapus Personally I would undelete it. It's a better count than both of ours and not really a copy of either – MickyT – 2017-12-18T17:22:10.170

@plannapus I agree with MickyT! – NofP – 2017-12-18T21:04:05.003

@NofP and MickyT: OK then, here it is

– plannapus – 2017-12-19T08:37:37.590

4

R, 66 bytes

This answer is more or less a medley of MickyT and NofP's answers, and on their request, here it is:

function(x,R=rle(rev(utf8ToInt(x)-48)))!max(R$v[-1])^(1/R$l[1])%%1

It takes x as a string.

> f=function(x,R=rle(rev(utf8ToInt(x)-48)))!max(R$v[-1])^(1/R$l[1])%%1
> f("41802000")
[1] TRUE
> f("100")
[1] TRUE
> f("123456788")
[1] FALSE
> f("451111111")
[1] FALSE
> f("234543454545444")
[1] FALSE
> f("12")
[1] TRUE
> f("41902000")
[1] FALSE

plannapus

Posted 2017-12-17T20:31:20.083

Reputation: 8 610

3

JavaScript (ES7), 66 bytes

Takes input as either a string or an array of characters. Returns a boolean.

f=([c,...s],m)=>s.some(n=>n-c)?f(s,c<m?m:c):!(m**(1/-~s.length)%1)

Test cases

f=([c,...s],m)=>s.some(n=>n-c)?f(s,c<m?m:c):!(m**(1/-~s.length)%1)

console.log(f(       '41802000')) // 1
console.log(f(            '100')) // 1
console.log(f(      '123456788')) // 0
console.log(f(      '451111111')) // 0
console.log(f('234543454545444')) // 0
console.log(f(             '12')) // 1

Arnauld

Posted 2017-12-17T20:31:20.083

Reputation: 111 334

3

Clean, 130 128 118 93 bytes

import StdEnv
@l#(b,a)=span((==)(last l))(reverse l)
=or[n^length b==last(sort a)\\n<-[0..9]]

Defines the function @, taking a list of integer digits.

Try it online!

Οurous

Posted 2017-12-17T20:31:20.083

Reputation: 7 916

3

Python 2, 95 78 bytes

  • Saved seventeen bytes thanks to Rod.
def f(s,i=~0):
	while s[i]==s[~0]:i-=1
	return int(max(s[:-~i]))**(1./~i)%1==0

Try it online!

Jonathan Frech

Posted 2017-12-17T20:31:20.083

Reputation: 6 681

You don't need o sort, you can just get the max, and since you already got i you can drop the len reaching 78 bytes

– Rod – 2017-12-18T10:17:09.143

@Rod Thanks a lot. – Jonathan Frech – 2017-12-18T18:48:53.380

2

C (gcc), 144 126 117 bytes

j,k,m;f(char*N){N+=j=strlen(N);k=~j;for(j=-1;m=N[j--]==N[j];);for(;k++<j;)m=fmax(N[k],m);j=!fmod(pow(m-48,1./~j),1);}

Try it online!

Jonathan Frech

Posted 2017-12-17T20:31:20.083

Reputation: 6 681

2

R, 93 bytes

function(x){n=nchar(x)
d=x%/%10^(n:1-1)%%10
i=max(which(d!=d[n]))
max(d[1:i])^(1/(n-i))%%1>0}

Try it online!

The code takes an integer as input and returns FALSE if the number is pleasing, and TRUE otherwise.

NofP

Posted 2017-12-17T20:31:20.083

Reputation: 754

2

Python 3, 88 85 bytes

def f(n):p=n.rstrip(n[-1]);a=int(max(p));b=len(n)-len(p);return round(a**(1/b))**b==a

Ungolfed:

def is_pleasing_number( n ):
    prefix = n.rstrip(n[-1])
    a = int(max(prefix))
    b = len(n) - len(prefix)
    return round(a ** (1 / b)) ** b == a
  • The input argument is expected to be a digit string
  • The output is either True or False.
  • Similar to yet developed independently of Halvard’s answer but uses floating point arithmetic in a way that doesn't suffer from rounding errors until a ** (1 / b) is off by at least 0.5 from b√a which requires a value above 253 (or whatever floating point radix and mantissa length Python happens to use, see sys.float_info).
  • Can be modified trivially to still work with arbitrary number bases between 2 and 36.

David Foerster

Posted 2017-12-17T20:31:20.083

Reputation: 260

@ovs: With a minor modification, yes. The function would have to take the base as an extra argument and pass it to the invocations of int and range. (At some point it would become more feasible to estimate the search range based ont a^(1/b) than to calculate large amounts of powers.) – David Foerster – 2017-12-18T18:11:37.893

1

Ruby, 64 bytes

->a{!([a[/(\d)\1*$/].size,$`.chars.max]*?x!~/x1$|^2x[49]|^3x8/)}

Input as a string, returns true if:

  • B==1 (no need to check A)
  • A==4 and B==2
  • A==9 and B==2
  • A==8 and B==3

Try it online!

G B

Posted 2017-12-17T20:31:20.083

Reputation: 11 099

1

Perl 6, 55 bytes

{m/(\d+?)((\d)$0*)$/;so any(^10)**$1.comb==$0.comb.max}

Try it online!

After the evaluation of the initial regex--which can only succeed if the input is a positive integer--$0 contains the initial part of the number, and $1 contains the trailing repeated digits.

The comb method without arguments, applied to a string, returns a list of the characters, which in numeric context evaluates to the length of the list. So $0.comb.max is the largest of the digits in the prefix, and $1.comb is the length of the suffix.

We then check whether any(^10) (ie, the or-junction of the numbers from 0-9), when raised to the power of the length of the suffix, is equal to the largest digit in the prefix. The so forces boolean evaluation of the resulting junction, which would otherwise be just fine on its own as a truthy value, but the challenge calls for just two distinct values to be returned.

Sean

Posted 2017-12-17T20:31:20.083

Reputation: 4 136

This is late, but since the input is guaranteed to be an integer, the regex can use . instead of \d. – DLosc – 2018-04-03T23:21:25.553

1

Kotlin, 106 bytes

fun String.p()=split(Regex("(?=(.)\\1*$)")).let{Math.pow((it[0].max()?:'0')-'0'+.0,1.0/(it.size-1))}%1==.0

Output: true/false

Try it online!

Damiano

Posted 2017-12-17T20:31:20.083

Reputation: 131

1

C# (.NET Core), 132 bytes

n=>{int A=0,B=1,s=1,i=n.Length-1;for(;i-->0;)if(n[i]==n[i+1]&s>0)B++;else{A=n[i]>A?n[i]:A;s=0;}return System.Math.Pow(A,1d/B)%1==0;}

Try it online!

Acknowledgements

-12 bytes thanks to @KevinCruijssen

DeGolfed

n=>{
    int A=0, // maximum digit
        B=1, // count of trailing identical numbers
        s=1, // 1 if dealing with trailing numbers, 0 otherwise
        i=n.Length-1;

    for(; i-- > 0;)
        if(n[i] == n[i+1] & s > 0)
            B++;
        else
        {
            A = n[i] > A? n[i] : A;
            s = 0;
        }

    return Math.Pow(A, 1d/B) % 1 == 0;
}

Ayb4btu

Posted 2017-12-17T20:31:20.083

Reputation: 541

I know it's been a while, but i=n.Length-2;for(;i>=0;i--) can be golfed to i=n.Length-1;for(;i-->0;) and && can be golfed to &. – Kevin Cruijssen – 2018-04-03T11:54:05.173

Oh, and you can golf 6 more bytes by removing the using System; and using System.Math.Pow directly. – Kevin Cruijssen – 2018-04-03T11:57:06.813

One last thing. You currently take a list of characters, but it's also allowed to take a list of digits. In which case the -48 can be golfed for -3 bytes. – Kevin Cruijssen – 2018-04-03T12:13:58.377

1

Add++, 21 bytes

L,BGubLV@¦+bMG1$/^1%!

Try it online!

It's been 3 and a half months, I hope I'm not ninja'ing anyone.

caird coinheringaahing

Posted 2017-12-17T20:31:20.083

Reputation: 13 702

1

Japt, 26 18 bytes

ó¶
o l
ñ o n qV v1

Try it online!


Takes input as a string, returns 1 for pleasing numbers, 0 otherwise.

Short explanation:

ó¶

Take the first input and split it by values where (x,y) => x===y is true. For example '41802000' to ['4','1','8','0','2','000'].

o l

Take the array from the first step, remove the last element and get its length, yielding B.

ñ o n qV v1

Find the largest element in the remaining array, yielding A, take it to the power 1/B and then return if the result is divisible by one.


First time working with Japt, very open to any recommendations.
Shaved off 8 bytes thanks to ETHproductions.

Nit

Posted 2017-12-17T20:31:20.083

Reputation: 2 667

Hey, welcome to Japt! Sorry I missed your answers at first. A few tips: 1) You can use an auto-function to turn the first line into just ó¶. 2) Not sure why you have the v in the second line, as it just converts the string to lowercase and has no effect on the length ;-) 3) You can avoid the !(U on the last line by changing %1 to v1, which returns 1 if the subject is divisible by 1 or 0 otherwise.

– ETHproductions – 2018-04-06T14:26:12.850

@ETHproductions Thanks a lot for your feedback, really appreciate it. I read about auto-functions before, but I still haven't quite gotten the hang of it, thanks for the example. I've incorporated the rest of your changes too, adding up to a total of 8 bytes lost. – Nit – 2018-04-06T14:38:01.183

0

Clojure, 168 bytes

(fn[x](let[y(reverse(vec x))z(count(take-while #(= %(first y))y))a(apply max(map #(-(int %)48)(drop z y)))b(Math/pow a(/ 1 z))](<(Math/abs(- b(Math/round b)))0.00001)))

Try it online!

Attilio

Posted 2017-12-17T20:31:20.083

Reputation: 131

0

Charcoal, 33 bytes

≔ESιθ⊞υ⊟θW⁼§υ⁰§θ±¹⊞υ⊟θ¬﹪XI⌈θ∕¹Lυ¹

Try it online! Link is to verbose version of code. Outputs a - for pleasing numbers. Explanation:

≔ESιθ

Split the input q into characters.

⊞υ⊟θ

Remove the last character from q and push it to u (predefined to an empty list).

W⁼§υ⁰§θ±¹⊞υ⊟θ

Repeatly pop and push while the last character of q is the first character of u.

¬﹪XI⌈θ∕¹Lυ¹

Take the maximum digit of q and raise it to the power of the reciprocal of the length of u, then check whether the result is an integer.

Neil

Posted 2017-12-17T20:31:20.083

Reputation: 95 035

0

Python 2, 91 85 bytes

s=`input()`;d=0
p=s.rstrip(s[-1])
exec"`d**(len(s)-len(p))`==max(p)>exit(1);d+=1;"*10

Try it online!

ovs

Posted 2017-12-17T20:31:20.083

Reputation: 21 408

0

Perl 5, 73 + 1 (-p) = 74 bytes

s/(.)\1*$//;$/=length$&;$_=(sort/./g)[-1];$q=$"++**$/while$q<$a;$_=$q==$a

Try it online!

Xcali

Posted 2017-12-17T20:31:20.083

Reputation: 7 671

0

Java 8, 125 bytes

a->{int A=0,B=1,f=1,i=a.length-1;for(;i-->0;)if(a[i]==a[i+1]&f>0)B++;else{A=a[i]>A?a[i]:A;f=0;}return Math.pow(A,1d/B)%1==0;}

Port of @Ayb4btu's C# .NET answer.

Try it online.

Explanation:

a->{                       // Method with digit-array parameter and boolean return-type
  int A=0,                 //  Maximum digit `A` as specified in the challenge description
      B=1,                 //  `B` as specified in the challenge description
      f=1,                 //  Flag-integer, starting at 1
      i=a.length-1;        //  Index integer `i`
  for(;i-->0;)             //  Loop `i` backwards over the digits (excluding the last)
    if(a[i]==a[i+1]        //   If the current and next digits are the same,
       &f>0)               //   and the flag is still 1
      B++;                 //    Increase `B` by 1
    else{                  //   Else:
      A=a[i]>A?            //    If the current digit is larger than `A` 
         a[i]              //     Replace `A` with the current digit
        :                  //    Else:
         A;                //     Leave `A` the same
      f=0;}                //    Set the flag-integer to 0
  return Math.pow(A,1d/B)  //  Return if `A` ^ (1/`B`)
    %1==0;}                //  is an exact integer

Kevin Cruijssen

Posted 2017-12-17T20:31:20.083

Reputation: 67 575

0

Pip, 32 22 21 bytes

'.N(#a-#Ya<|a@v)RTMXy

Uses 1 for falsey and 0 for truthy, saving a byte. Try it online!

DLosc

Posted 2017-12-17T20:31:20.083

Reputation: 21 213

0

Pyth, 29 bytes

JezWqezJ=Pz=hZ)K@sh.MsZzZqKsK

Test suite

Python 3 translation:
Z=0
z=input()
J=z[-1]
while z[-1]==J:
    z=z[:-1]
    Z+=1
K=max(map(int,z))**(1/Z)
print(K==int(K))

hakr14

Posted 2017-12-17T20:31:20.083

Reputation: 1 295