46
\$\begingroup\$

Challenge:

Create a program that accepts a positive integer and checks if it can be written in the form of (3^x)-1, where X is another positive integer.

If it can, output X

If it can't, output -1 or a falsy statement.

Example inputs/outputs

Input:

2

It can be written as (3^1) - 1, so we output x which is 1

Output:

1

Input:

26

26 can be written as (3^3) - 1, so we output x (3)

Output:

3

Input:

1024

1024 can't be written in the form of (3^x) - 1, so we output -1

Output:

-1

This is so least amount of bytes wins


Related OEIS: A024023

\$\endgroup\$
16
  • 6
    \$\begingroup\$ I ask to output X because I believe it's more challenging that way. Simply finding if it is of format 3^x - 1 would be too easy for a challenge, in my opinion. \$\endgroup\$
    – Offtkp
    Commented Jan 6, 2017 at 14:56
  • 2
    \$\begingroup\$ Unless if it's a falsy statement in your programming language, then no. \$\endgroup\$
    – Offtkp
    Commented Jan 6, 2017 at 16:57
  • 3
    \$\begingroup\$ May I want the number to be input in ternary? \$\endgroup\$ Commented Jan 6, 2017 at 17:35
  • 3
    \$\begingroup\$ having to handle non-negative intergers would make 0 3^0-1 a valid output and thus not useable as false, \$\endgroup\$
    – Jasen
    Commented Jan 7, 2017 at 7:40
  • 3
    \$\begingroup\$ anyone thinking of using log() in their answer should confirm it giives the correct answer 5 when 242 is input. \$\endgroup\$
    – Jasen
    Commented Jan 7, 2017 at 9:57

73 Answers 73

2
\$\begingroup\$

Brachylog, 6 bytes

;3^₍-₁

Try it online!

Takes input through the Output variable.

Explanation

;3         [?, 3]
  ^₍       3^?
    -₁     3^? - 1 = Input

This will unify ? with the right value if possible, and output false. otherwise.

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

Python, 64 bytes

Outputs False if the number cannot be written in that format.

def f(n):L=[3**x-1for x in range(n)];print n in L and L.index(n)

This also works in 64 bytes, and prints empty string as a falsy output:

def f(n):
 try:print[3**x-1for x in range(n)].index(n)
 except:0

A creative solution for 65 bytes, outputting 0 for falsy:

lambda n:-~",".join(`3**x-1`for x in range(n+1)).find(',%s,'%n)/2
\$\endgroup\$
4
  • \$\begingroup\$ Does not output x nor -1. \$\endgroup\$
    – dfernan
    Commented Jan 6, 2017 at 15:17
  • \$\begingroup\$ The program should output x instead of n in case of a match. \$\endgroup\$
    – dfernan
    Commented Jan 6, 2017 at 15:20
  • \$\begingroup\$ No, it should output the positive integer that when replaced with X, you get the input. The question refers to X as a variable, not as a string \$\endgroup\$
    – Offtkp
    Commented Jan 6, 2017 at 15:22
  • \$\begingroup\$ @P.Ktinos Fixed it. \$\endgroup\$
    – mbomb007
    Commented Jan 6, 2017 at 15:31
1
\$\begingroup\$

Pyth, 10 bytes

*J@hQ3!%J1

Try it here!

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

Julia, 30 bytes

n->findfirst(n.==3.^(0:n)-1)-1

It's a simple function - it creates a vector that has a true only in the corresponding position in 3^a-1, where a is a vector containing integers between 0 and n. It finds the "first" position that is true and subtracts 1 (if it's all false, the find evaluates to zero, and it returns -1).

As 0:n has 0 in the first spot, the subtract 1 corrects for indexing and also enables the -1 false response.

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

Pyke, 9 6 bytes

3m^Qh@

Try it here!

3m^    -  map(3**i, range(input))
     @ - V in ^
   Qh  -  input + 1

Old 9 byte version:

b3'l}\2q*

Try it here!

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

Pyth 8 bytes

xm^3dUQh

     UQ  # generate all values 1..Q (Q is the input)
 m^3d    # map 3^d over this ^ list
x      h # find the input+1 (hQ) in the result of the last command

Try here

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

R, 34 25 bytes

a=log(scan()+1,3);a*!a%%1

Calculate the base 3 logarithm of the input + 1. Test if the result is an integer, if it is it outputs it, if not it outputs 0 as falsey value. Thanks to @Billywob for the extra 9 bytes off!

Test cases:

> a=log(scan()+1,3);a*!a%%1
1: 1024
2: 
Read 1 item
[1] 0

> a=log(scan()+1,3);a*!a%%1
1: 26
2: 
Read 1 item
[1] 3

Old version at 34 bytes which outputs -1 as falsey value.

a=log(scan()+1,3);`if`(!a%%1,a,-1)
\$\endgroup\$
2
  • \$\begingroup\$ If you do a*!a%%1 it will output a if true and 0 otherwise and you can skip the if thing. \$\endgroup\$
    – Billywob
    Commented Jan 6, 2017 at 16:07
  • \$\begingroup\$ The spec says "If it can't, output -1 or a falsy statement." and 0 is interpreted as FALSE in R so I would say it's valid. \$\endgroup\$
    – Billywob
    Commented Jan 6, 2017 at 16:19
1
\$\begingroup\$

C, 81 bytes

i,j,k;f(n){for(i=0;++i<n;){for(k=3,j=0;++j<i;k*=3);if(n==k-1)return i;}return-1;}
\$\endgroup\$
3
  • \$\begingroup\$ I think you save bytes by using pow(3,i) instead of defining your own. Gcc complains about the missing #include <math.h> but compiles it anyway. I did have to cast to int. You also may be able to gain some by adding an r variable, initializing to -1, and then if(n==k-1)r=i;}return r;} \$\endgroup\$
    – nmjcman101
    Commented Jan 6, 2017 at 18:54
  • 2
    \$\begingroup\$ @nmjcman101 Thanks, but pow() produces some incorrect results because of floating point inaccuracy. (When cast to int, 2.9999 will be 2, not 3). Adding a variable r sounds like a good idea, but it actually results in a 2 bytes longer code. \$\endgroup\$
    – Steadybox
    Commented Jan 6, 2017 at 22:33
  • \$\begingroup\$ yeah, log doesn't work, pow probably won't either. \$\endgroup\$
    – Jasen
    Commented Jan 7, 2017 at 9:28
1
\$\begingroup\$

Japt, 8 bytes

o m!³a°U

Try it online!

This code expands into the following:

Uo m!p3 a++U

Uo            // Create the range [0...U).
   m!p3       // Map each item X to 3**X.
        a++U  // Take the index of U+1. Returns -1 if it doesn't exist.
              // Implicit: output result of last expression
\$\endgroup\$
1
  • \$\begingroup\$ Very nice solution. \$\endgroup\$
    – Oliver
    Commented Jan 7, 2017 at 6:04
1
\$\begingroup\$

GolfScript, 11 bytes

~..3\?\)%!*

Try it online!

Uses the fact that 3n is divisible by n+1 if and only if n+1 itself is a power of 3. Outputs its input n if n+1 is a power of 3, otherwise outputs 0 (which is falsy in GolfScript).

De-golfed:

~             # eval the input, converting it from string to integer
 ..           # make two copies of the input number
   3\?        # raise 3 to the power of the input number
      \)%     # reduce the result modulo the input number plus one
         !    # boolean negate the result, mapping 0 to 1 and all other values to 0
          *   # multiply the input number with the result

Ps. Here's a simple test harness that runs the code above (minus the initial ~, which is not needed since the inputs are already numbers) on all integers from 0 to 9999 and prints those for which it returns a truthy result:

10000,{ ..3\?\)%!* },`

The output of this program should be:

[2 8 26 80 242 728 2186 6560]

(The output doesn't include 0 because, even though the formula used does correctly detect it as one less than a power of 3, the result is still 0 × 1 = 0, and thus falsy. Fortunately, 0 is not a positive integer, and thus isn't a valid input for this challenge anyway.)

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

Octave, 23 bytes

@(x)find(3.^(1:x)-1==x)

Verify all test cases!

Explanation:

This is an anonymous function that takes a positive integer x as input. .^ is element-wise power in Octave, so 3.^(1:x) is 3^1, 3^2, 3^3 .... Subtracting 1 gives 3^1-1, 3^2-1, 3^3-1 ... which can be compared to x.

find(a,b) takes a vector a as input, and attempts to find the scalar b in that vector and returns its index. If it's not found then it will output an empty matrix []. An empty matrix is a falsey value in Octave.

find(3.^(1:x)-1==x) searches for x in the vector 3^1-1, 3^2-1, 3^3-1 ... and attempts to return its index. If it's not in the vector then it returns an empty (falsey) matrix.

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

C, 76 bytes

main(i,a,c){scanf("%d",&a);for(c=0,++a;i<a;i*=3,++c);printf("%d",(i==a)*c);}
\$\endgroup\$
1
\$\begingroup\$

Sagemath, 45 bytes

This is simply @dfernan's solution repackaged as Sagemath (which is basically Python + some math libraries loaded by default and syntactic sugar).

In Sagemath, we can avoid the import math and we can use ^ for exponentiation, so we save a few chars.

def f(n):x=ceil(log(n,3));print((3^x-1==n)*x)

Test it online

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

c++ 60 bytes

int f(n){float o=log1p(n)/log(3);return o/floor(o)!=1?-1:o;}

explanation:

int f(n){             
  float o=log1p(n)/log(3);       // eval for x using log3 function 
  return o/floor(o)!=1?-1:o;     // if no remainder output X 
}
\$\endgroup\$
4
  • \$\begingroup\$ I think you don't have to use uint16_t. You can use normal int. \$\endgroup\$ Commented Jan 8, 2017 at 19:55
  • \$\begingroup\$ I guess I could to save a few bytes but it seemed to me that if I wasn't safeguarding against negative integer input then I wasn't following the guidelines. \$\endgroup\$
    – mreff555
    Commented Jan 14, 2017 at 21:04
  • \$\begingroup\$ this compile to me: int f(n){float o=log1p(n)/log(3);return o/floor(o)!=1?-1:o;} \$\endgroup\$
    – user58988
    Commented Apr 29, 2017 at 15:53
  • 1
    \$\begingroup\$ @mreff555 You don't need to safeguard against negative input, you can assume positive input. \$\endgroup\$ Commented Apr 29, 2017 at 16:05
1
\$\begingroup\$

Python 2, 34 bytes

lambda n:(~n>>3**n%-~n*n)**4/80%80

Try it online!

Works for all Python ints, up to at least 2^100.

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

Pip, 13 bytes

aTB:3MNa=2&#a

Try it online!

Explanation

               a is 1st command-line argument (implicit)
aTB:3          Convert a to base 3 and assign back to a
     MNa=2     Does the min of a's digits equal 2?
          &    Logical-and
           #a  Length of a
               If there are non-2 digits, we get the falsey value 0; otherwise, we get
               the number of digits
\$\endgroup\$
0
1
\$\begingroup\$

05AB1E, 6 bytes

>3.n.ï

Try it online!

> increments, 3 pushes a 3 to the stack, .n find the logarithm with base 3, checks if it is equal to its integer part.

Returns 0 for falsy: If it can't, output -1 or a falsy statement.

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

APL (Dyalog), 11 bytes

⊢|⊢⍳⍨¯1+3*⍳

Try it online!

Uses ⎕IO←0.

How?

- range of 0 to n-1.

3* - raise 3 to the power of each element.

¯1+ - decrement each by 1.

⊢⍳⍨ - search the index of n in that list (if not exists, this would return the maximum index plus 1 - which is n.

⊢| - modulo by n. This would keep the index, if found, and zero-out numbers not contained in the list that would produce n % n = 0.


APL (Dyalog), 14 bytes

(∧/×≢)2=3⊥⍣¯1⊢

Try it online!

\$\endgroup\$
3
  • \$\begingroup\$ "26 can be written as (3^3) - 1" 124 can be written as (5^3)-1 but your code for 124 not print 5 print 0 \$\endgroup\$
    – user58988
    Commented Feb 2, 2018 at 15:45
  • \$\begingroup\$ Ok I confuse exponent and base \$\endgroup\$
    – user58988
    Commented Feb 2, 2018 at 15:52
  • \$\begingroup\$ @RosLuP you mind deleting the comments? people use to DV without much thinking when seeing these \$\endgroup\$
    – Uriel
    Commented Feb 3, 2018 at 16:17
1
\$\begingroup\$

APL NARS, 14 chars or 28 bytes

{r×r=⌊r←3⍟1+⍵}

Test:

  f←{r×r=⌊r←3⍟1+⍵}
  f 2     
1
  f 26
3
  f 1024
0
\$\endgroup\$
2
  • \$\begingroup\$ This is 28 bytes in NARS, but exactly the same solution is only 14 bytes in Dyalog APL. Also, you can save two bytes by conversion to tradfn, r×r=⌊r←3⍟1+⎕, letting the program prompt for input. \$\endgroup\$
    – Adám
    Commented Dec 25, 2017 at 16:15
  • \$\begingroup\$ @Adám i prefer functions \$\endgroup\$
    – user58988
    Commented Dec 25, 2017 at 19:47
1
\$\begingroup\$

Befunge-93, 26 bytes

&1+>:3%v
1+\^v-1_3/\
.@.$_

Try It Online

Prints 0 as the falsey.

How it Works

&1+... Gets the input and adds one
......
......

...>:3%v    Check if the number is divisible by 3
1+\^..._3/\ If not, divide the number by 3 and increment a counter
...         Repeat until the number is not divisible by 3

.........   If the final number is a one, print the counter
....v-1_... Else pop the counter and print a 0
.@.$_       End the program
\$\endgroup\$
1
\$\begingroup\$

Factor, 30 bytes

[ 1 + 3 over [0,b) n^v index ]

Try it online!

Port of Dennis' Jelly answer. The index word conveniently returns f (the only falsy value in Factor) when the item is not found.

[              ! anonymous lambda
  1 + 3 over   ! ( n+1 3 n+1 )
  [0,b)        ! ( n+1 3 {0..n} )
  n^v          ! ( n+1 {3^0..3^n} )
  index        ! 0-based index of n+1 in {3^0..3^n}; false if not found
]

Factor, 45 bytes

[ 3 >base dup [ 50 = ] all? swap length and ]

Try it online!

A base-conversion approach.

[                    ! anonymous lambda, accepting a positive integer n
  3 >base            ! ( str ) convert to base-3 string
  dup [ 50 = ] all?  ! ( str ? ) test if it is all 2's
  swap length and    ! ( len/f ) if true, return the length of str
                     ! otherwise return false
]
\$\endgroup\$
1
\$\begingroup\$

Japt , 6 bytes

Outputs undefined, which is falsey, instead of -1.

NøÓ3pU

Try it

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

Vyxal, 7 bytes

›3•D⌊=*

Try it Online!

-1 thanks to Steffan.

A different approach that's annoyingly longer.

›       # Increment
 3•     # Log 3
   D⌊=  # Check if it's an integer
      * # Multiply by that
\$\endgroup\$
1
  • \$\begingroup\$ @Steffan I guess, although it's kinda ambiiguous as 0 is an allowed output. \$\endgroup\$
    – emanresu A
    Commented Jul 23, 2022 at 23:33
1
\$\begingroup\$

tinylisp, 68 bytes

(d F(q((N A)(i(l N A)()(i(e A N)0(a 1(F N(a(a A A)A
(q((N)(F(a N 1)1

The solution is the anonymous function on the second line. Try it online!

Explanation

The function F does most of the work. It takes a target number N and an accumulator A. If N is a power of three, it returns the exponent; otherwise, it returns nil, which is a falsey value.

(d F               ; Define F
 (q                ; to be a function
  ((N A)           ; that takes arguments N and A:
   (i(l N A)       ; If N is less than A,
    ()             ; return nil
    (i(e A N)      ; Else, if A is equal to N,
     0             ; return 0
     (a 1          ; Else, add 1 to the result of
      (F N         ; a recursive call with the same N
       (a(a A A)A  ; and three times the A (A+A+A)

If N equals three to the X, the 0 base case will be reached at the Xth level of recursion, meaning that 1 will be added to it X times for a result of X. If the () base case is reached instead, 1 will be added to it some number of times, but adding a number to nil gives nil (and an error message).

The submission function is then just a wrapper around F:

(q          ; A function
 ((N)       ; that takes argument N:
  (F        ; Call F with arguments
   (a N 1)  ; N+1
   1        ; and initial accumulator 1
\$\endgroup\$
1
\$\begingroup\$

Thunno D, \$ 7 \log_{256}(96) \approx \$ 5.76 bytes

R3@1-Ah

Attempt This Online!

Explanation

R3@1-Ah  # D flag duplicates implicit input
R        # Push range(0, input)
 3@      # 3 ** each
   1-    # Decrement
     Ah  # Index of input in this list
         # (0-indexed, -1 if not found)
\$\endgroup\$
1
\$\begingroup\$

Stax, 6 bytes

ö♥ô·ô₧

Run and debug it

This unpacks to the following:

Stax, 7 bytes

f3s#vx=

Run and debug it

f       # filter over 1..input
 3s#    # 3^n
    v   # -1
     x= # is equal to the input

Outputs nothing if falsy

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

Nekomata, 5 bytes

3D←P∑

Attempt This Online!

3D      Convert to base 3
  ←     Decrement every digit
   P    Check if all digits are positive
    ∑   Sum
\$\endgroup\$
0
\$\begingroup\$

JavaScript (ES6), 40 bytes

f=(n,p=0,k=1)=>n<k?n>k-2&&p:f(n,p+1,k*3)

Returns false or the power. A simple port of @Arnauld's ES7 answer would have taken 43 bytes.

\$\endgroup\$
1
  • \$\begingroup\$ I think f=(n,p,k=1)=>n<k?n>k-2&&p:f(n,-~p,k*3) works and saves 2 bytes. \$\endgroup\$
    – Arnauld
    Commented Jan 7, 2017 at 0:24
0
\$\begingroup\$

PHP, 36 47 bytes

If log(input+1,3) differs from its integer value, print 0; else print the logarithm:
<?=(0|$x=log($argv[1]+1,3))-$x?0:$x; (36 bytes) fails for 242.
<?=strstr($x=log($argv[1]+1,3),".")?0:$x; and <?=(0|$x=log($argv[1]+1,3))-$x>1e-7?0:$x; (41 bytes) may fail for larger $x.

This version is safe:

for(;3**++$x<$n=1+$argv[1];);echo$n<3**$x?0:$x;

1.Loop $x up from 1 while 3^$x is smaller than argument+1.
2.Print 0 if the expression is larger than input+1, $x else.

Takes input from command line argument. Run with -nr.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ gives wrong answer for 242 input \$\endgroup\$
    – Jasen
    Commented Jan 7, 2017 at 9:22
  • \$\begingroup\$ @Jasen: The downvote was ridiculous, but it´s fixed now. \$\endgroup\$
    – Titus
    Commented Jan 7, 2017 at 11:36
0
\$\begingroup\$

Java 7, 180 bytes

class A{public static void main(String[]q)throws Exception{int a,b=0;while((a=System.in.read()-48)>=0)b=b*10+(a);double k=Math.log(b+1)/Math.log(3);System.out.print(k%1==0?k:-1);}}

Really simple approach. Input, then add one, then log3 the number, and if it's a integer, print it; otherwise, print -1. Could use some work.

Only works up to (3^19)-1.

\$\endgroup\$
5
  • \$\begingroup\$ Why is this non-competing? The Non-Competing status is only reserved for languages or language features that were added after the challenge was posted. \$\endgroup\$
    – user41805
    Commented Jan 7, 2017 at 11:10
  • \$\begingroup\$ As I said, size doesn't matter, so this can compete. \$\endgroup\$
    – Offtkp
    Commented Jan 7, 2017 at 20:55
  • \$\begingroup\$ @KritixiLithos Oh okay. I wasn't aware of the exact meaning of Non-Competing. Thanks. Also, I'll update the title. \$\endgroup\$
    – hyperneutrino
    Commented Jan 8, 2017 at 3:19
  • 1
    \$\begingroup\$ You can use interface A{...} and drop the public from main(). Why do you have (a) instead of a in the while loop. I think you can use float k=... instead of double k=.... Should be -5 bytes if I counted right. \$\endgroup\$ Commented Jan 8, 2017 at 20:04
  • \$\begingroup\$ @RomanGräf I appreciate your suggestions; however, none of them are of any use for me, unfortunately. Your first suggestion only works in Java 8, and there is already a far better Java 8 solution out there. I have (a) in the while loop because I am doing a comparison of an assignment statement, and assignment has the lowest priority on the order of operations and thus requires a set of brackets around it. Finally, I have double because Math#log returns a double and casting would obviously be much slower. Regardless, thank you for the suggestions, but I will not be incorporating them. \$\endgroup\$
    – hyperneutrino
    Commented Jan 9, 2017 at 3:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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