15
\$\begingroup\$

Barbrack

Your task is to write a program or function that takes a non-negative integer (in decimal or any other convenient base for your language), and output a number in the numbering system Barbrack.

What's that?

Barbrack is a numbering system I made up that can represent non-negative integers. Zero is represented with an empty string or an underscore, one is represented with [], and all other positive integers can be represented with a brack.

A brack is delimited with brackets [] and works as follows (with an example of 84):

  1. Take your number a and find its prime factorization. In this case, the prime factorization of 84 is 22*31(*50)*71.
  2. Find the indices of these primes, where the index of 2 is 1. In this case, the index of 3 is 2, since it's the prime right after 2; and the index of 7 is 4, since it's the fourth prime.
  3. Take the exponents of each prime, and put them in brackets in increasing order of the size of the prime, with consecutive exponents being separated by bars (|). So the general format is [exponent of 2|exponent of 3|exponent of 5…]—in this case, [2|1|0|1]. Minimize the number of cells!
  4. Recursively calculate the exponents in Barbrack, remembering that 0 is the empty string and 1 is []. So [2|1|0|1] => [[1]|[]||[]] => [[[]]|[]||[]].
  5. Output the final result.

Test inputs

0     -> (nothing)
1     -> []
2     -> [[]]
5     -> [||[]]
27    -> [|[|[]]]
45    -> [|[[]]|[]]
54    -> [[]|[|[]]]
84    -> [[[]]|[]||[]]
65535 -> [|[]|[]||||[](48 bars)[]]
65536 -> [[[[[]]]]]

(sidenote: (48 bars) means 48 consecutive bars in the actual output)

Rules

  • Standard loopholes apply.
  • No input in Barbrack! This isn't a cat challenge!
  • You may replace [] with any other paired delimeter, like () or {}. However, the vertical bars need to be actual vertical bars.
  • Whitespace is not allowed within the number, but is allowed outside of it (for example, a trailing newline).
  • The program should be able to fully parse any number given infinite time and memory.

Scoring

Scores are counted by minimum bytes on a per-language basis.

\$\endgroup\$
5
  • 2
    \$\begingroup\$ Closely related (but not a duplicate) \$\endgroup\$
    – DLosc
    Sep 29, 2023 at 22:08
  • \$\begingroup\$ Can you provide some weird examples with numbers with prime factors of degree greater than 2? Like 8 for example which is 2^3 \$\endgroup\$
    – AZTECCO
    Sep 30, 2023 at 12:45
  • 1
    \$\begingroup\$ Done! Thank you for the idea! \$\endgroup\$
    – Someone
    Sep 30, 2023 at 15:54
  • \$\begingroup\$ Since the _ output needs bytes, what if you took 5 points away if the code outputs _ for 0? \$\endgroup\$
    – Joao-3
    Sep 30, 2023 at 16:50
  • 1
    \$\begingroup\$ What would be the rationale behind outputting _ for 0? Is it a language that doesn't support empty strings? \$\endgroup\$
    – Someone
    Sep 30, 2023 at 16:54

11 Answers 11

5
\$\begingroup\$

Jelly, 12 bytes

ÆE߀j”|Ø[jxẸ

Try it online!

A monadic link that takes an integer as its argument and returns a string.

Explanation

ÆE߀j”|Ø[jxẸ­⁡​‎‎⁡⁠⁡‏⁠‎⁡⁠⁢‏‏​⁡⁠⁡‌⁢​‎‎⁡⁠⁣‏⁠‎⁡⁠⁤‏‏​⁡⁠⁡‌⁣​‎‎⁡⁠⁢⁡‏⁠‎⁡⁠⁢⁢‏⁠‎⁡⁠⁢⁣‏⁠‏​⁡⁠⁡‌⁤​‎‎⁡⁠⁢⁤‏⁠‎⁡⁠⁣⁡‏⁠‎⁡⁠⁣⁢‏‏​⁡⁠⁡‌⁢⁡​‎‎⁡⁠⁣⁣‏⁠‎⁡⁠⁣⁤‏‏​⁡⁠⁡‌­
ÆE            # ‎⁡Prime exponents
  ߀          # ‎⁢Current (main) link for each member of the list of exponents
    j”|       # ‎⁣Join with the bar character
       Ø[j    # ‎⁤Wrap in square brackets
          xẸ  # ‎⁢⁡Repeat once if original argument was non-zero else repeat zero times (effectively preserves current value if argument was non-zero else returns empty list)
💎

Created with the help of Luminespire.

Conversion back from barbrack

Jelly, 13 bytes

ṖḊṣ”|߀ÆẸµ0¹?

Try it online!

A monadic link that takes a string and returns an integer. The TIO link converts to barbrack and then back.

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

Vyxal, 13 bytes

λ[∆Ǐvx\|jøB|¤

Try it Online!

λ             # Define a recursive lambda
 [            # If the input is nonzero
     x        # Recurse on
    v         # Each of
  ∆Ǐ          # The prime exponents of n 
      \|j     # Join by |
         øB   # And wrap in []
 [         |¤ # Else, if it's zero, return the empty string.
\$\endgroup\$
4
\$\begingroup\$

Python, 113 bytes

def f(n):
 P=i=2;r=''
 while w:=n>1:
  while n%i<1:n//=i;w+=1
  r+=P%i*'|'+f(w-1);P*=i*i*2;i+=1
 return'[%s]'%r*n

Attempt This Online!

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

JavaScript (ES6), 96 bytes

f=(n,q=1)=>n?q>n?"]":["|["[(g=d=>q%d--?g(d):q<3|-d)(q++)]]+f((g=_=>n%q?0:1+g(n/=q))())+f(n,q):""

Try it online!

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

Haskell, 196 bytes

n#f|n`mod`f==0=1+(n`div`f)#f|0<1=0
p 1=[]
p n=(:)<*>p.div n$until((<1).mod n)(+1)2
f 0=""
f 1="[]"
f n='[':concat(init$filter(\n->mod(product[1..n-1]^2)n>0)[2..maximum.p$n]>>=(:["|"]).f.(n#))++"]"

Try it online!

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Welcome! It would be scary to do this in Haskell:) btw I think you missed nmodf==0 can be <1 \$\endgroup\$
    – AZTECCO
    Oct 6, 2023 at 9:05
2
\$\begingroup\$

Python3, 227 bytes

R=range
def f(n):
 if n<2:return'[]'*n
 d,K={},{}
 while n>1:
  for i in R(2,n+1):
   if(i==2 or all(i%j for j in R(2,i))):
    K[i]=1
    if 0==n%i:n//=i;d[i]=d.get(i,0)+1;break
 return'['+'|'.join(f(d.get(i,0))for i in K)+']'

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ @ovs Thank you, updated \$\endgroup\$
    – Ajax1234
    Sep 30, 2023 at 14:44
1
\$\begingroup\$

Charcoal, 99 87 80 bytes

⊞υNWυ«≔∨⊟υωι¿⁼ι⁺ωιι«≔⟦⟧θ≔²ηW⊖ι«⊞θ⌕X⁰⮌↨ιη⁰≧÷Xη§θ±¹ι⊞θ|≦⊕ηW¬⌊﹪η…²η≦⊕η»⊞υ]FΦ⮌θλ⊞υκ[

Try it online! Link is to verbose version of code. Explanation:

⊞υN

Start by processing the input integer.

Wυ«

Repeat until there are no more values to be processed.

≔∨⊟υωι

Get the next value, or the empty string if it is zero.

¿⁼ι⁺ωιι«

If the next value is a string then print it, otherwise:

≔⟦⟧θ

Start collecting prime powers.

≔²η

Start at the first prime.

W⊖ι«

Repeat until the integer is reduced to 1.

⊞θ⌕X⁰⮌↨ιη⁰

Add the multiplicity of this prime factor to the list of prime powers.

≧÷Xη§θ±¹ι

Divide the integer by the power of the prime to the multiplicity.

⊞θ|

Add a separator to the list of prime powers.

≦⊕ηW¬⌊﹪η…²η≦⊕η

Find the next prime by brute force.

»⊞υ]

Push a ] for later output.

FΦ⮌θλ⊞υκ

Push each prime power in reverse order, but without the leading separator.

[

Print [. Subsequent passes through the loop will then process the prime powers, separators and ].

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

J, 34 bytes

*#1|.'][',1}.&;'|'(,$:)&.>_&q: ::$

Attempt This Online!

_&q: ::$ Get the prime exponents. If that errors (0), get an empty array instead.
'|'(,$:)&.> For each exponent, call the entire function recursively and prepend a bar to the result.
1}.&; Join into a single string and remove the first bar.
1|.'][', Wrap in brackets by prepending both, then rotating one to the back.
*# Replicate by sign of input. This makes sure 0 returns an empty string.

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

05AB1E, 27 bytes

"D!i„[]×ëÓ®δ.V'|ý'[ì']«"©.V

As usual, 05AB1E isn't the best when it comes to recursive challenges. And since there isn't a way to interpret or convert a list [] to a string "[]", it becomes even longer..

Try it online or verify all test cases.

Here an alternative that's 1 byte longer:

Δ.γd}εÐdi!i„[]×ëÓ'|ý…[ÿ]}}}J

Try it online or verify all test cases.

Explanation:

"..."             # Define the recursive string below
     ©            # Store this string in variable `®` (without popping)
      .V          # Pop and execute it as 05AB1E code
                  # (after which the result is output implicitly)

D                 # Duplicate the current integer
 !i               # Pop the copy, and if it's 0 or 1:
   „[]×           #  Repeat "[]" 0 or 1 times as string
  ë               # Else (it's >=2):
   Ó              #  Get a list of exponents of its prime factorization
     δ            #  Map over each integer:
    ® .V          #   Do a recursive call
   '|ý           '#  Join the list with "|"-delimiter
      '[ì']«      #  Prepend "[" and append "]"
Δ                 # Loop until the result no longer changes,
                  # using the implicit input in the first iteration:
 .γ }             #  Adjacent group-by the string by:
   d              #   Check whether it's a digit
 ε                #  Map over each group:
  Ð               #   Triplicate the current string
   di             #   If it's a number:
     !i„[]×ëÓ'|ý '#    Similar as above
     …[ÿ]         #    Prepend "[" and append "]"
     }            #    Close the inner if-else statements
    }             #   Close the outer if-statement
 }                #  Close the map
  J               #  Join this mapped list of groups back together to a single string
                  # (after which the result is output implicitly)
\$\endgroup\$
1
\$\begingroup\$

Scala, 335 bytes

Port of @Ajax1234's Python answer in Scala.

\$ \color{red}{\text{But the scala code fails on same cases. Any help would be appreciated.}} \$


335 bytes, it can be golfed much more.

Golfed version. Try it online!

import scala.util.control.Breaks._
def f(n:Int):String={if(n<2)return"[]"*n;var d=Map[Int,Int]();var K=List[Int]();var num=n
while(num>1){breakable{for(i<-2 to num){if(i==2||(2 until i).forall(i%_!=0)){K=i::K;if(num%i==0){num/=i;d=d.updated(i,d.getOrElse(i,0)+1);break}}}}}
"["+K.distinct.map(i=>f(d.getOrElse(i,0))).mkString("|")+"]"}

Ungolfed version. Try it online!

import scala.util.control.Breaks._

object Main {
  def main(args: Array[String]): Unit = {
    println(f(0))
    println(f(1))
    println(f(2))
    println(f(65536))
  }

  def f(n: Int): String = {
    if (n < 2) return "[]" * n

    var d = Map[Int, Int]()
    var K = List[Int]()
    var num = n

    while (num > 1) {
      breakable({
      for (i <- 2 to num) {
        if (i == 2 || (2 until i).forall(i % _ != 0)) {
          K = i :: K
          if (num % i == 0) {
            num /= i
            d = d.updated(i, d.getOrElse(i, 0) + 1)
            break
          }
        }
      }
      })
    }

    "[" + K.distinct.map(i => f(d.getOrElse(i, 0))).mkString("|") + "]"
  }
}
\$\endgroup\$
1
  • \$\begingroup\$ Some minor tips: you can use a lambda instead of a full method (also, the return type can be inferred, I think), you can use .mkString("[","|","]"), and you can use >0 inside the .forall. But I think you would save even more bytes if you didn't directly port the Python answer. The import to allow breaks is costing you a lot of bytes. \$\endgroup\$
    – user
    Oct 1, 2023 at 14:57
1
\$\begingroup\$

Ruby, 109 bytes

require"prime"
f=->n{n<1?"":"[#{n<2?"":Prime.each((q=n.prime_division)[-1][0]).map{|x|f[q.to_h[x]||0]}*?|}]"}

Try it online!

f=->n{        _f_ takes an integer _n_ and
n<1?""        returns "" if _n_ == 0
:"[#{...}]"   else returns a string enclosed in brackets composed of:
n<2?""          empty string if _n_ == 1
:Prime.each(    else we take all primes up to 
(q=n.prime_division)[-1][0]) 
                maximum factor( saving factorization in _q_ )
.map{|x|        and map them by:
f[...]            calling _f_ recursively with 
q.to_h[x]         hash made from factorization( gives us powers )
||0               for primes not in factorization _q_ default _nil_ is converted to 0
}*?|            finally join with `|`
\$\endgroup\$

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.