title: Additive Persistence

text:
# Question
Title: Additive Persistence
*The shortest code to pass all possibilities wins.*

In mathematics, the persistence of a number measures how many times a certain operation must be applied to its digits until some certain fixed condition is reached. You can determine the additive persistence of a positive integer by adding the digits of the integer and repeating. You would keep adding the digits of the sum until a single digit number is found. The number of repetitions it took to reach that single digit number is the additive persistence of that number.

**Example using 84523:**

```
84523
8 + 4 + 5 + 2 + 3 = 22
2 + 2 = 4

It took two repetitions to find the single digit number.
So the additive persistence of 84523 is 2.

```

You will be given a sequence of positive integers that you have to calculate the additive persistence of. Each line will contain a different integer to process. Input may be in any standard I/O methods.

For each integer, you must output the integer, followed by a single space, followed by its additive persistence. Each integer processed must be on its own line.

## Test Cases

---

**Input Output**

```
99999999999 3
10 1
8 0
19999999999999999999999 4
6234 2
74621 2
39 2
2677889 3
0 0

```

# Answer
## K - 29 Chars

Input is a filename passed as an argument, 29 chars not including filename.

```
`0:{5:x,-1+#(+/10_vs)\x}'.:'0:"file"

```
* 35 -\> 31: Remove outside function.
* 31 -\> 29: Remove parens.
> 7 votes

# Answer
**Python 84 Chars**

```
while 1:
 m=n=int(raw_input());c=0
 while n>9:c+=1;n=sum(map(int,str(n)))
 print m,c

```
> 4 votes

# Answer
## Python (93 bytes)

```
f=lambda n,c:n>9and f(sum(map(int,str(n))),c+1)or c
while 1:n=int(raw_input());print n,f(n,0)

```
> 4 votes

# Answer
## Haskell, 100 characters

```
p[d]=0
p d=1+(p.show.sum$map((-48+).fromEnum)d)
f n=n++' ':shows(p n)"\n"
main=interact$(f=<<).lines

```
> 4 votes

# Answer
# Husk, ~~10~~ 15 bytes

<sub>+5 bytes for horrible I/O requirement</sub>

```
m(wΓ·,LU¡oΣdr)¶

```

Try it online!

### Explanation

To support multiple inputs, we need to use `m(₁r)¶` (where  is the function doing the interesting computation):

```
m(₁r)¶  -- expects newline-separated inputs: "x₁␤x₂␤…␤xₙ"
     ¶  -- split on newlines: ["x₁","x₂",…,"xₙ"]
m(  )   -- map over each string
 ( r)   -- | read integer: [x₁,x₂,…,xₙ]
 (₁ )   -- | apply the function described below

```

The function  does the following:

```
wΓ·,LU¡(Σd)  -- input is an integer, eg: 1234
      ¡(  )  -- iterate the following forever and collect results in list:
       ( d)  -- | digits: [1,2,3,4]
       (Σ )  -- | sum: 10
             -- : [1234,10,1,1,1,…
     U       -- keep longest prefix until repetition: [1234,10,1]
 Γ           -- pattern match (x = first element (1234), xs = tail ([10,1])) with:
  · L        -- | length of xs: 2
   ,         -- | construct tuple: (1234,2)
w            -- join with space: "1234 2"

```
> 4 votes

# Answer
### bash, 105 chars

```
while read x
do
for((i=0,z=x;x>9;i++))do
for((y=0;x>0;y+=x%10,x/=10))do :
done
x=$y
done
echo $z $i
done

```

Hardly any golfing actually involved, but I can't see how to improve it.
> 3 votes

# Answer
## Haskell - 114

```
s t n|n>9=s(t+1)$sum$map(read.(:[]))$show n|1>0=show t
f n=show n++" "++s 0n++"\n"
main=interact$(f.read=<<).lines

```
> 3 votes

# Answer
## Ruby, 85 Chars

```
puts $<.map{|n|v=n.chop!;c=0;[c+=1,n="#{n.sum-n.size*48}"] while n[1];[v,c]*' '}*"\n"

```

I had to borrow the "sum-size\*48" idea from Alex, because it's just too neat to miss (in Ruby at least).
> 3 votes

# Answer
## Golfscript, 40 chars

```
n%{.:${;${48-}%{+}*`:$,}%.,1>\1?+' '\n}%

```
> 3 votes

# Answer
## J - 45 Chars

Reads from stdin

```
(,' ',[:":@<:@#+/&.:("."0)^:a:)&><;._2(1!:1)3

```
> 3 votes

# Answer
## c -- 519

**(or 137 if you credit me for the framework...)**

Rather than solving just this one operation, I decided to produce a framework for solving **all persistence problems**.

```
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef char*(*O)(char*);
char*b(char*s){long long int v=0,i,l=0;char*t=0;l=strlen(s);t=malloc(l+2);
for(i=0;i<l;i++)v+=s[i]-'0';snprintf(t,l+2,"%lld",v);return t;}
int a(char**s,O o){int r;char*n;n=o(*s);r=!strcmp(*s,n);free(*s);
*s=n;return r;}
int main(int c, char**v){size_t l, m=0;char *d,*n=0;O o=b;FILE*f=stdin;
while(((l=getline(&n,&m,f))>1)&&!feof(f)){int i=0;n=strsep(&n,"\n");
d=strdup(n);while(!a(&n,o))i++;printf("%s %d\n",d,i);free(d);free(n);n=0;m=0;}}

```

**Only the two lines starting from `char*b` are unique to this problem.**

It treats the input as strings, meaning that leading "0"s are not strip before the output stage.

The above has had comments, error checking and reporting, and file reading (input must come from the standard input) striped out of:

```
/* persistence.c
 *
 * A general framework for finding the "persistence" of input strings
 * on opperations.
 *
 * Persistence is defined as the number of times we must apply
 *
 *    value_n+1 <-- Opperation(value_n)
 *
 * before we first reach a fixed point.
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../getline.h"

/* A function pointer type for operations */
typedef char*(op_func)(char*);
typedef op_func* op_ptr;
/* Op functions must
 * + Accept the signature above
 * + return a point to a newly allocated buffer containing the updated str
 */

char* addop(char*s){
  int i,l=0;
  long long int v=0;
  char *t=NULL;
  /* protect against bad input */
  if (NULL==s) return s;
  /* allocate the new buffer */
  l = strlen(s);
  t = malloc(l+2);
  if (NULL==t) return t;
  /* walk the characters of the original adding as we go */
  for (i=0; i<l; i++) v += s[i]-'0';
  //fprintf(stderr,"   '%s' (%d) yields %lld\n",s,l,v);
  snprintf(t,l+2,"%lld",v);
  //fprintf(stderr,"   %lld is converted to '%s'\n",v,t);
  return t;
}

/* Apply op(str), return true if the argument is a fixed point fo
 * falsse otherwise,
 */
int apply(char**str, op_ptr op){
  int r;
  char*nstr;
  /* protect against bad input */
  if ( NULL==op ) exit(1);
  if ( NULL==*str ) exit(4);
  /* apply */
  nstr = op(*str);
  /* test for bad output */
  if ( NULL==nstr ) exit(2);
  r = !strcmp(*str,nstr);
  /* free previous buffer, and reasign the new one */
  free(*str);
  *str = nstr;
  return r;
}

int main(int argc, char**argv){
  size_t len, llen=0;
  char *c,*line=NULL;
  op_ptr op=addop;
  FILE *f=stdin;
  if (argc > 1) f = fopen(argv[1],"r");
  while( ((len=getline(&line,&llen,f))>1) && line!=NULL && !feof(f) ){
    int i=0;
    line=strsep(&line,"\n"); // Strip the ending newline
    /* keep a copy for later */
    c = strdup(line);
    /* count necessary applications */
    while(!apply(&line,op)) i++;
    printf("%s %d\n",c,i);
    /* memory management */
    free(c);
    free(line);
    line=NULL;
    llen=0;
  }
}

```

A little more could be saved if we were willing to leak memory like a sieve. Likewise by `#define`ing return and the like, but at this point I don't care to make it any uglier.
> 3 votes

# Answer
# APL (Dyalog Unicode), ~~21~~ 17 bytes

```
{⍵≤9:0⋄1+∇+/⍎¨⍕⍵}

```

-4 bytes from Jo King.

Try it online!

```
{s←+/⍎¨⍕⍵⋄⍵≤9:0⋄1+∇s}

```

Try it online!

## Explanation

```
{s←+/⍎¨⍕⍵⋄⍵≤9:0⋄1+∇s} ⍵ → input
       ⍕⍵             convert ⍵ to string
     ⍎¨               execute each character(getting digits)
   +/                 reduce to sum of digits
 s←                   assign to s
          ⍵≤9:        if number is single digit
              0       return 0, stop recursion
                1+∇s  Otherwise return 1+f(sum)

```
> 3 votes

# Answer
## J, 74 chars

```
i=:<;._2(1!:1)3
i&((],' ',":@(0 i.~9<[:".([:":[:+/"."0)^:(i.9)))@>@{~)i.#i

```

### Edits

* **(86 → 83)** Some Caps `[:` to Ats `@`
* **(83 → 79)** Unneeded parentheses
* **(79 → 75)** Changing `0".` to `".` simplifies things
* **(75 → 74)** Better Cutting

### E.g

```
i=:<;._2(1!:1)3
74621
39
2677889
0
i&((],' ',":@(0 i.~9<[:".([:":[:+/"."0)^:(i.9)))@>@{~)i.#i
74621 2
39 2
2677889 3
0 0

```
> 2 votes

# Answer
# K (ngn/k), 16 bytes

**Solution:**

```
{x,#1_(+/10\)\x}

```

Try it online!

**Explanation:**

```
{x,#1_(+/10\)\x} / the solution
{              } / lambda taking implicit x
      (     )\x  / iterate until convergence
         10\     / split into base-10 (123 => 1 2 3)
       +/        / sum
    1_           / drop first result (iterate returns input as first result)
   #             / count length of result
 x,              / prepend x (original input)

```
> 2 votes

# Answer
# Jelly, 12 bytes

```
żDS$Ƭ€Ẉ’ƊK€Y

```

Try it online!

Takes input as a list of integers. +3 bytes to input as a multiline string.

+3 bytes (or +6) for restrictive I/O formats, yay

## How it works

```
żDS$Ƭ€Ẉ’ƊK€Y - Main link. Takes a list l on the left
        Ɗ    - To l:
   $         -   Group the previous 2 links into a monad f(n):
 D           -     Digits
  S          -     Sum
    Ƭ€       -   Over each n in l, repeatedly apply f(n) until a fixed point,
                  yielding [n, f(n), f(f(n)), ...]
      Ẉ      -   Get the length of each loop
       ’     -   Decrement each
ż            - Zip the loop lengths with l
         K€  - Join each by spaces
           Y - Join by newlines

```
> 2 votes

# Answer
# Vyxal `aj`, ~~9~~ 8 bytes

```
ƛ⁽∑↔L‹"Ṅ

```

Try it Online!

Explanation:

```
          # Treat all the inputs as a list (`a` flag)
ƛ         # On each item (n) in that list
 ⁽        # Create a single element lambda
  ∑       # That sums the digits of a number
   ↔      # Apply that function on n until it doesn't change
          # and return the intermediate values in a list
    L     # Get the length of that list
     ‹    # Decrement it to ignore the last time the function is called
      "   # Pair that with n
       Ṅ  # Join the pair by a space
          # Join the mapped inputs by new lines (`j` flag)
          # Implicitly print

```
> 2 votes

# Answer
I think this is about the best I can come up with.

**Ruby 101 Chars**

```
f=->(n){n.sum-n.size*48}
$<.each{|l|i=0;i+=1 while(i+=1;n=f[(n||l.chop!).to_s])>10
puts "#{l} #{i}"}

```
> 1 votes

# Answer
**PARI/GP 101 Chars**

```
s(n)=r=0;while(n>0,r+=n%10;n\=10);r
f(n)=c=0;while(n>9,c++;n=s(n));c
while(n=input(),print(n," ",f(n)))

```

Unfortunately, there's no input function for GP, so i guess this lacks the IO part. :( Fixed: Thanks Eelvex! :)
> 1 votes

# Answer
**Javascript - 95**

```
i=prompt();while(i>9){i=''+i;t=0;for(j=0;j<i.length;j++)t+=parseInt(i.charAt(j));i=t;}alert(t);

```

EDIT: Whoops does'nt do the multi-lines
> 1 votes

# Answer
# J, 78

```
f=:[:+/"."0&":
r=:>:@$:@f`0:@.(=f)
(4(1!:2)~LF,~[:":@([,r)".@,&'x');._2(1!:1)3

```

Recursive solution. Reads from stdin. **Writes to stdout**, so cut me some slack - it does take an extra 18-ish characters.
> 1 votes

# Answer
## Perl - 77 characters

```
sub'_{split//,shift;@_<2?0:1+_(eval join'+',@_)}chop,print$_,$",(_$_),$/for<>

```
> 1 votes

# Answer
### scala 173:

```
def s(n:BigInt):BigInt=if(n<=9)n else n%10+s(n/10)
def d(n:BigInt):Int=if(n<10)0 else 1+d(s(n))
Iterator.continually(readInt).takeWhile(_>0).foreach(i=>println(i+" "+d(i)))

```
> 1 votes

# Answer
# JavaScript, ~~57~~ 47 bytes

*-10 bytes thanks to @l4m2!*

```
f=(s,c=0)=>s>9?f(eval([...s+""].join`+`),++c):c

```

Try it online!
> 1 votes

# Answer
# Japt `-R`, ~~21~~ 19 bytes

```
Ë+S+(DsÊÉ ÆD=ìxÃâ Ê

```

Try it
> 1 votes

# Answer
# 05AB1E, ~~13~~ 10 bytes

```
ε.ΓSO}g}ø»

```

-3 bytes thanks to *@Steffan*

Input as a list of integers.

Try it online.

**Explanation:**

```
ε      # Map each integer in the (implicit) input to:
 .Γ    #  Loop until the integer no longer changes,
       #  keeping all intermediate steps in a list:
   S   #   Convert the integer to a list of digits
    O  #   Sum those digits together
  }g   #  After the inner loop: pop and push the length
}ø     # After the outer map: zip/transpose it with the (implicit) input to create a
       # list of pairs
  »    # Join each pair by a space, and then the list of strings by newlines
       # (after which the result is output implicitly)

```
> 1 votes

# Answer
# MathGolf, 11 bytes

```
hÅ_Σ]▀£(k ?

```

Try it online!

~~Incredibly inefficient, but we don't care about that. Basically, using the fact that the additive persistence of a number is smaller than or equal to the number itself.~~

Uses the fact that the additive persistence is less than or equal to the number of digits of the number. Passes all test cases with ease now.

The input format, while suboptimal for some languages, is actually the standard method of taking multiple test cases as input in MathGolf. Each line of the input is processed as its own program execution, and output is separated by a single newline for each execution.

## Explanation (using `n = 6234`)

```
h             push length of number without popping (6234, 4)
 Å            loop 4 times using next 2 operators
  _           duplicate TOS
   Σ          get the digit sum
    ]         wrap stack in array
              this gives the array [6234, 15, 6, 6, 6]
     ▀        unique elements of string/list ([6234, 15, 6])
      £       length of array/string with pop (3)
       (      decrement (2)
        k ?   push input, space, and rotate top 3 elements to produce output (6234 2)

```
> 1 votes

# Answer
# Julia, 92 (29) bytes

```
f(n)=n>9&&(f∘sum∘digits)(n)+1

```

Edit: With correct printing it's 92:

```
f(n)=n>9&&(f∘sum∘digits)(n)+1
while(n=parse(Int128,readline()))≢π
println("$n ",f(n)%Int)end

```
> 1 votes

# Answer
# Stax, ~~8~~ 11 bytes

```
ªwæMε∞ö?îm⌐

```

Run and debug it

+3 bytes thanks to @Khuldraeseth (the first answer didn't have compliant output)
> 1 votes

# Answer
# Jq `-r`, 52 bytes

```
[while(length>1;explode|map(.-48)|add|@text)]|length

-r                    # take one number per line, converting it to a string

                explode                              # the character codes
                       |map(.-48)                    # subtract ascii zero from each
                                 |add                # sum the elements
                                     |@text          # back to text, (shorter than
                                                     # tostring and tojson)
 while(length>1;                           )         # produces *all* the intermediate
                                                     # results while the string length>1
[                                           ]        # collected into an array
                                             |length # the length of these results

```

Not answering the multiplicative persistence now because jq doesn't have a `product` builtin :)

Jq play it!
> 1 votes

# Answer
# Knight, 54 bytes

```
;=iP;=r 0;W<1Li;=s 0;Wi;=s+sA Ai=iGi 1Li;=i+""s=r+1rOr

```

Try it online!
> 1 votes

# Answer
# Ly, 21 bytes

```
0s+1[pSy,![lu;]&+l`s]

```

Try it online!

A pretty straight forward interpretation of the challenge rules this time.

```
0s+1[pSy,![lu;]ç]
0s                    - initialize the backup cell to 0 (iteration count)
  +                   - load input number, absorbing the 0 on the stack
   1                  - push a truthy value to enter loop
    [p              ] - infinite loop
      S               - convert number on top of stack to digits
       y              - push the number of digit (stack size)
        `!            - decrement and convert truthiness
          [   ]       - if/then, executes is number is a single digit
           lu;        - load backup cell, print as number, end program
               &+     - sum the digits on the stack
                 l`s  - load backup cell (iterations) increment and save

```
> 1 votes

# Answer
# Tcl, 95 bytes

```
proc P {v n\ 0} {set V $v
while \$v>9 {set v [expr [join [split $v ""] +]]
incr n}
puts $V\ $n}

```

Try it online!
> 0 votes

# Answer
# C (gcc), ~~87~~ 85 bytes

* Saved two bytes thanks to ceilingcat; pulling the `t=s` assignment forward and using `(t=s)[1]` ~ `*((t=s)+1)` ~ `*(1+(t=s))` ~ `1[t=s]`.

```
f(n,p){char*t,s[99];for(p=0;sprintf(s,"%d",n),1[t=s];p++)for(n=0;*t;n+=*t++-48);n=p;}

```

Try it online!
> 0 votes

# Answer
# Perl 5, 65 bytes

```
$b=0;$q=s/\n//r;$_=eval s/./+$&/gr while y///c>1&&++$b;say"$q $b"

```

Try it online!
> 0 votes

# Answer
# Java (OpenJDK 8), 79 bytes

```
a->{int d=0;while(a/10>0){int c=0;d++;while(a>0){c+=a%10;a/=10;}a=c;}return d;}

```

Try it online!

There's probable potential to golf it further, but I'll look into that in the future, but for now, I'm pretty happy with this little result.
> 0 votes

# Answer
# **Python 3**, 82 bytes

```
while 1:f=lambda n:n//10and 1+f(sum(map(int,str(n))));i=input();print(i,f(int(i)))

```
> 0 votes

# Answer
# Japt, 28 bytes

```
Ë+S+(@D=X©A<D©ì x ªD D<AÃaÃ·
Ë                            // Map over the inputs and return each, followed by
 +S+                         // a space, followed by the number's persistence.
      D=     ©ì x            // To find it, fold the number up
        X©A<D     ªD         // if we can (handles unfoldable cases),
    (@               D<AÃa   // until it can't be folded up any further.
                          Ã· // Then, join everything up with newlines.

```

Try it online!
> 0 votes

# Answer
# PHP, 72+1 bytes

+1 for `-R` flag.

```
for($i=0,$a=$argn;$a>9;$i++)$a=array_sum(str_split($a));echo"$argn $i
";

```

Run as pipe with `-R`.

* running PHP as pipe will execute the code once for every input line
* but it does not unset variables inbetween; so `$i` must be initialized.
(Also, it would print nothing instead of `0` for single digits without the initialization.)
> 0 votes

# Answer
# Bash+coreutils, 83 bytes

```
[ $1 -le 9 ]&&exit $2
let x=$2+1
for z in `fold -w1<<<$1`
do let y+=$z
done
a $y $x

```

Try it online!

Should be saved to a script called `a` and placed in the system's `PATH`, as it calls itself recursively. Takes input from command line, like `a 1999`. Returns by exit code.

TIO has some limitations on what you can do with a script, so there's some boilerplate code to make this run in the header.

Prints an error to `stderr` for input larger than bash integers can handle, but since the actual computation is done with strings, it still gives the right result anyway.
> 0 votes

# Answer
# Python 3, 76 bytes

```
def f(n,i=0,p=0):p=p or n;f(sum(map(int,str(n))),i+1,p)if n>9else print(p,i)

```

Try it online!

---

Without I/O restrictions:

# Python 3, 54 bytes

```
f=lambda n,i=0:f(sum(map(int,str(n))),i+1)if n>9else i

```

Try it online!
> 0 votes

# Answer
## Swift 5, 106 bytes

```
func a(_ s:S,_ i:I)->(S,I){if s.count<=1{return(s,i)};return a(S(s.compactMap{I(S($0))}.reduce(0,+)),i+1)}

```

Try it online!
> 0 votes

# Answer
# Python 2, 62 bytes

```
f=lambda x,i=0:f(`sum(int(i)for i in x)`,i+1)if len(x)>1else i

```
> 0 votes

# Answer
# Python 3, 50 bytes

```
f=lambda n:0if n<10else-~f(eval('+'.join(str(n))))

```

Recursive function. Takes an integer, returns an integer.

**Explanation:**

```
# create a lambda function which takes one argument, and assign it to f
f=lambda n:\
    # if n is 0-9, it's persistence 0
    0if n<10\
        # otherwise, add one to the running total and recursively call f
        # ( ~ will invert the returned number, equivalent to -n-1)
        # (negating that gives you -(-n-1) = n+1)
        else-~f(
            # convert integet to string, join each character with a '+'
            # gives a string like '1+2+3+4+...+n'
            # evaluate the string as an expression, giving a new integer
            # pass that integer back into f
            eval('+'.join(str(n)))
        )

```
> 0 votes

# Answer
# Pyth, 17 bytes

```
FG.Qs[Gdtl.usjNTG

```

Try it online!

If I can instead of values on different lines, take a list of numbers (in the format `[9999999999, 10, 8, etc.]`), then -1 byte by replacing `.Q` with `Q`

```
F                  # For
 G.Q               #   G in the complete input (split by newlines)
    s[             #     join the list as string, create list from the following values:
      Gd           #       G, " " (for output formatting),
        tl         #       decrement length of
          .u    G  #          List of all intermediate results until there's a returning result, with starting value G
            s      #            reduce on + (add all list elements) the list:
             j     #              convert to integer as list:
              N    #                The current value (implicit input to .u)
               T   #                in base 10 (T=10)

```
> 0 votes

# Answer
# \>\<\>, 36 bytes

```
0{:a(7$.0}\~1+!
~n
1:,a}+{%a:/?(1:-%

```

Try it online!
> 0 votes

# Answer
# Nibbles, 7 bytes (14 nibbles)

```
:$,>>`.$/`@~$+

```

```
                    # (implicitly map over input):
:$                  # prepend input onto
  ,                 # length
   >>               # (without first item) of
     `.             # iterate while unique
       $            # starting with input number:
         `@~$       #   convert to base-10 digits
        /           #   and fold over this list
             +      #     adding its elements

```
> 0 votes

# Answer
# Go, 77 bytes

```
func f(n int)int{s:=0
if n<10{return 0}
for;n>0;n/=10{s+=n%10}
return 1+f(s)}

```

Attempt This Online!
> 0 votes

---
Tags: code-golf, math, arithmetic, repeated-transformation
---


# Question
Title: How many light changes will a 7-segment display need?
# Problem

Assume you have a single 7-segment display without a decimal point, so 7 "lines" that can be labelled A through G as seen here.

This display will only show the numbers from 0 to 9 as usual, like so:

Any time this display changes from one number to another, some of its lights will have to change their state from on to off or vice versa, or they can simply stay on, e.g. in the case of 1 -\> 2, segment B can stay on, while segments A, G, E, D need to turn on, and C needs to turn off; for the change 6 -\> 8, only segment B needs to be changed from off to on.

# Task

Your task is to take a sequence of numbers as reasonably formatted input and output the amount of on and off changes as the display shows each number in the sequence in input order. You should output a separate score for "on" and "off" in a reasonable format. A light that stays on between numbers shall not be counted towards either on or off. The initial state of the display is all lights off, so the first number will always count as only "on" changes. The final state will be the last number displayed.

# Test cases

```
123 -> 7, 2 (7 on, 2 off)
111 -> 2, 0 (2 segments on, then no changes)
987 -> 7, 4
2468 -> 11, 4 (thanks to @ovs for catching a mistake here!)

```

This is , so the shortest code wins. Also, this is my first post here, so I hope I made no mistakes for my submission :)

# Answer
# APL (Dyalog Extended), 34 bytes

Anonymous tacit prefix function taking a list of numbers. Requires 0-based indexing (`⎕IO←0`).

```
2(<⌿,⍥(≢⍸)>⌿)0⍪11⎕DR'~0my3[_p␡{'⊇⍪

```

Try it online!

change list into column matrix

`'~0my3[_p␡{'⊇` map to ASCII characters with corresponding pit pattern

`11⎕DR` get corresponding binary **D**ata **R**epresentation as 8-column table

`0⍪` prepend an all-zero row

`2(``)` apply the following tacit function with 2 as left argument:

`>⌿` indicate where a 1 is above a 0 (lit. greater-than reduction over vertical windows of size 2)

`<⌿,⍥(``)` concatenate with where-0-is-above-1 as follows:

list of indices where there are 1s

tally the indices (this gives the count of 1s)
> 5 votes

# Answer
# 05AB1E, ~~40~~ 35 bytes

```
•z]∍1:pIªy•2в7ôDIнè(sã€øÆIü2è«˜®1‚¢

```

-5 bytes thanks to *@Steffan*

Try it online or verify all test cases.

**Explanation:**

```
•z]∍1:pIªy• # Push compressed integer 1098931065668123279355
  2в        # Convert it to base-2 as list: [1,1,1,0,1,1,1,0,0,1,0,0,1,0,1,0,1,1,1,0,1,1,0,1,1,0,1,1,0,1,1,1,0,1,0,1,1,0,1,0,1,1,1,1,0,1,1,1,1,1,0,1,0,0,1,0,1,1,1,1,1,1,1,1,1,1,1,0,1,1]
    7ô      # Split it into parts of size 7: [[1,1,1,0,1,1,1],[0,0,1,0,0,1,0],[1,0,1,1,1,0,1],[1,0,1,1,0,1,1],[0,1,1,1,0,1,0],[1,1,0,1,0,1,1],[1,1,0,1,1,1,1],[1,0,1,0,0,1,0],[1,1,1,1,1,1,1],[1,1,1,1,0,1,1]]
D           # Duplicate it
 Iн         # Push the first digit of the input
   è        # Use it to index into this list of lists
    (       # Negate all 1s to -1s in the list
s           # Swap so the duplicated list is at the top again
 ã          # Create all possible pairs using the cartesian power with itself
  €ø        # Zip/transpose each inner pair of lists; swapping rows/columns
    Æ       # Reduce each inner-most pair by subtracting
     I      # Push the input-integer again
      ü2    # Create overlapping pairs of it
        è   # Use that to index into the other list
«           # Merge the two lists together
 ˜          # Flatten it
  ®1‚       # Push pair [-1,1]
     ¢      # Count the amount of -1s and 1s in the list
            # (after which this pair is output implicitly as result)

```

See this 05AB1E tip of mine (sections *How to compress large integers?* and *How to compress integer lists?*) to understand why `•z]∍1:pIªy•` is `1098931065668123279355` and `•z]∍1:pIªy•2в` is `[1,1,1,0,1,1,1,0,0,1,0,0,1,0,1,0,1,1,1,0,1,1,0,1,1,0,1,1,0,1,1,1,0,1,0,1,1,0,1,0,1,1,1,1,0,1,1,1,1,1,0,1,0,0,1,0,1,1,1,1,1,1,1,1,1,1,1,0,1,1]`.
> 3 votes

# Answer
# JavaScript (Node.js), 92 bytes

Expects a list of digits. Returns `[off, on]`.

Contains some unprintable characters.

```
a=>a.map(n=>(g=k=>k&&g(k/2,o[q&1]+=k&1,q/=2))(x^(x=q=Buffer('?[Ofm}o')[n])),o=[x=0,0])&&o

```

Try it online!

### How?

Given the segment bitmask \\$x\\$ of the previous digit and the segment bitmask \\$q\\$ of the new digit, we compute \\$k=x\operatorname{XOR}q\\$ and use the helper function \\$g\\$ to update the *off* and *on* counters which are stored in the array \\$o\[\\:\]\\$:

```
g = k =>       // k = result of the XOR between the 2 bitmasks
k &&           // stop when k = 0, which actually happens because
               // of arithmetic underflow because we use k / 2
               // rather than k >> 1 to save a byte
g(             // otherwise, do a recursive call:
  k / 2,       //   pass k / 2 for the next iteration
  o[q & 1] +=  //   select the counter according to the LSB of q
    k & 1,     //   increment it if the LSB of k is set
  q /= 2       //   divide q by 2
)              // end of recursive call

```

---

# JavaScript (ES6), 99 bytes

An alternate version without `Buffer()`.

The order of the segment bits and the XOR value were chosen to optimize the overall length of the lookup code.

```
a=>a.map(n=>(g=k=>k&&g(k/2,o[q&1]+=k&1,q/=2))(x^(x=q=[6,90,44,8,80,1,5,74,4][n]^123)),o=[x=0,0])&&o

```

Try it online!
> 3 votes

# Answer
# PARI/GP, 107 bytes

-4 bytes and fixed a bug thanks to @Arnauld.

```
a->d=127;sum(i=1,#a,[g(c=[2,91,40,9,81,5,4,27,0,1][1+a[i]],d),g(d,d=c)])
g(a,b)=sumdigits(bitand(-1-a,b),2)
```

Attempt This Online!
> 2 votes

# Answer
# Python, ~~116~~ 112 bytes

*-4 bytes thanks to @Kevin Cruijssen*

```
def f(s):
    A=X=Y=0
    for b in s:B=b'~0my3[_p\x7f{'[b];X+=(~A&B).bit_count();Y+=(A&~B).bit_count();A=B
    print(X,Y)
```

Attempt This Online!
> 2 votes

# Answer
# Rust, 147 bytes

```
|a|{let(b,mut e,f)=(b"~0my3[_p{",0,|a,b:u8,c:u8|a+(b^c&b).count_ones());a.iter().fold((0,0),|(l,r),&d|{let c=(f(l,b[d],e),f(r,e,b[d]));e=b[d];c})}

```

Try it online!

Note that the space in the byte string is really the ASCII delete character (code point `0x7f`). The basic idea is that the set bits are stored as a mask packed in a byte string, and the changed bits are detected with some bit twiddling, similar to the other answers from practical langs (although not the same- we've all taken different approaches for the same general technique, at least so far).
> 2 votes

# Answer
# C (gcc), <sup>~~136~~</sup> 134 bytes

```
#define B+=__builtin_popcount((d^c)
i;c;d;x;y;f(a,n)int*a;{for(i=x=y=d=0;n--;d=c)c="{HW^l>?X\x7f~"[a[i++]],x B&c),y B&d);*a=x;a[1]=y;}

```

Try it online!

*Saved 2 bytes thanks to ceilingcat!!!*

Inputs a pointer to an array of digits to display and its length (because C pointers carry no length info).
Return the number of lights turned on and the number turned off through the input pointer.
> 1 votes

# Answer
# Vyxal, 41 bytes

```
k-»>xWƛo4ø₅=»b7ẇ:?hiN$2ẋΠv∩vvƒ-?S2l⌊İJfvO

```

Try it online or verify all test cases.

## How?

```
k-»>xWƛo4ø₅=»b7ẇ:?hiN$2ẋΠv∩vvƒ-?S2l⌊İJfvO
k-                                         # Push [-1, 1] (will be used later)
  »>xWƛo4ø₅=»                              # Push compressed integer 1098931065668123279355
             b                             # Convert to binary as a list
              7ẇ                           # Split into chunks of size 7
                :                          # Duplicate
                 ?h                        # Push the first digit of the input
                   i                       # Index it into the list
                    N                      # Negate: replace all 1s with -1
                     $                     # Swap so the list of size-7 chunks are at the top again
                      2ẋΠ                  # Cartesian product with self
                         v∩                # For each, transpose
                           vvƒ-            # For each inner pair, reduce by subtraction
                               ?S          # Push stringified input
                                 2l        # Get all overlapping pairs
                                   ⌊       # Convert them to integers
                                    İ      # Index these into the other list
                                     J     # Join the two lists together
                                      f    # Flatten
                                       vO  # Count the number of -1s and 1s in this list

```
> 1 votes

# Answer
# Charcoal, 44 bytes

```
ＩＥ²Ｌ⭆⪪”←＆⊞YJΣζ⁹)Ｇ；⧴4L⁴↷U³”¶Φθ‹⁼ι№λ§⁺ θξ⁼ι№λν

```

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

```
  ²                         Literal integer `2`
 Ｅ                          Map over implicit range
      ...                   Compressed string
     ⪪                      Split on
         ¶                  Literal newline
    ⭆                       Map over elements and join
           θ                Input string
          Φ                 Filtered where
              ι             Outer value
             ⁼              Equals
               №            Count of
                            Literal space
                  ⁺         Concatenated with
                    θ       Input string
                 §          Indexed by
                     ξ      Inner index
                λ           In current string piece
            ‹               Is less than
                       ι    Outer value
                      ⁼     Equals
                        №   Count of
                          ν Current input character
                         λ  In current string piece
   Ｌ                        Take the length
Ｉ                           Cast to string
                            Implicitly print

```

The compressed string splits to the list  `1237`,  `14`,  `56`,  `017`,  `134579`,  `147`,  `2` which for each segment contains the digits (including the initial "off" state as a "digit") where the segment is off.
> 0 votes

# Answer
# Perl 5, 96 bytes

```
tr/0-9/\167\3\136\37\53\75\175\7\177\77/;@_=($_,"\0$_");print unpack"%b*",$_[$_]&~$_[!$_]for 0,1

```

Try it online!

## Explanation

Input arrives in `$_`, pre-trimmed to just digits

Convert each digit into a pattern of bits corresponding to the segments that are turned on. The order of bits doesn't matter as long as they're consistent, so this order was chosen so that the whole list is represented with the fewest (octal) digits.

(`tr` modifies `$_` in-place)

```
tr/0-9/\167\3\136\37\53\75\175\7\177\77/;

```

Make a copy with the starting blank included; keep both in the predefined `@_` array

```
@_ = ($_, "\0$_");

```

(Now when we perform bitwise operations on these two values, it will apply the operation to each pair of consecutive bytes.)

Loop (twice) ...

```
for 0,1

```

... to perform the following forwards and backwards, so we get both the "turned on" and "turned off" counts. (Note: loop iterator is `$_`, which we no longer need it to hold the input.)

Mask each byte (of the transformed input string) with the "previous" byte, resulting in a string of bytes with bits set indicating change in one direction (which is why we do the whole thing twice):

```
$_[$_] & ~ $_[!$_]

```

(`!$_` changes 0 to 1 and 1 to 0; `(B & ~ A)` gives you the bits that aren't set in A that are set in B)

Count the `1` bits from the expression above:

```
unpack "%b*",

```

Output the result:

```
print

```

Invoke Perl with the `-l` and `-n` options, for example, as:

```
perl -ln -e '«program here»' <<<'«input here»'

```

Each line of input is treated as a separate test case; after each test, the "turn on" and "turn off" counts are output on two separate lines.
> 0 votes

---
Tags: code-golf
---


title: Finding the power sandwich

text:
# Question
Title: Finding the power sandwich
# Introduction

Finding the *closest* power to a number is a common enough problem. But what if you need both the next-highest and next-lowest power? In this challenge you must find the closest powers to a given number - the 'power sandwich' if you will, where the given number is the filling and the powers are the bread. Mmm, tasty.

# Challenge

Given a power **P \>0** and a number **N \>0**, output the largest integer **x^P** that is smaller or equal to **N**, and the smallest integer **y^P** that is greater or equal to **N**.

Input should be taken as a list of two positive (\>0) integers, first the power P and then the number N. Output should be a list of two integers, the first being smaller or equal to N, the second being greater or equal to N, and both being a power of P.

If N is a power of P already, the output should be the list \[N, N\].

This is , so the shortest code (as measured in bytes) wins.

# Example Input and Output

Input:

> \[2, 17\]

Output:

> \[16, 25\]

Explanation: 16 is the biggest square number (power of 2) less than or equal to 17, and 25 is the smallest square number greater or equal to 17.

# Test cases

```
[2, 24] -> [16, 25]
[2, 50] -> [49, 64]
[3, 8] -> [8, 8]
[1, 25] -> [25, 25]
[3, 25] -> [8, 27]
[4, 4097] -> [4096, 6561]
[2, 10081] -> [10000, 10201]
[11, 2814661] -> [177147, 4194304]
[6, 1679616] -> [1000000, 1771561]

```

# Answer
# JavaScript (ES7), 39 bytes

Expects `(p)(n)`.

```
p=>n=>[x=(q=n**(1/p)|0)**p,(q+=x<n)**p]

```

Try it online!

### Alternate version (same size)

```
p=>n=>[0,1].map(i=>(n--**(1/p)+i|0)**p)

```

Try it online!
> 6 votes

# Answer
# , ~~36~~ ~~35~~ 33 bytes

```
\(P,N)abs(c(r<-N^(1/P),-r)%/%1)^P

```

Attempt This Online!
> 5 votes

# Answer
# Vyxal, 7 bytes

```
Ėe₍⌊⌈$e

```

Try it Online!

Trivial implementation.

```
Ėe₍⌊⌈$e
Ėe       # Exponentiate N with the reciprocal of P
  ₍⌊⌈    # Pair results of floor, ceil in a list
     $e  # Swap (returns first input) and exponentiate with P

```
> 4 votes

# Answer
# Python, 46 bytes

*based on port of Arnauld's JavaScript answer*

```
lambda p,n:[int(q:=n**(1/p))**p,(-(-q//1))**p]

```

Attempt This Online!

`floor` and `ceil` of p-th root to the power of p
> 3 votes

# Answer
# BQN, 10 bytes

```
(⌊⋈⌈)∘√´⋆⊑

```

Try it here.

Explanation:

```
(⌊⋈⌈)∘√´⋆⊑ # tacit function which takes a list [P,N]
 ⌊⋈⌈       # take the floor paired with the ceil
(   )∘√´   # of the P-th root of N
        ⋆⊑ # and raise to the power P

```
> 3 votes

# Answer
# Desmos, 51 bytes

```
f(l)=[floor(l[2]^{1/l})^l[1],ceil(l[2]^{1/l})^l[1]]

```

Try it on Desmos! Expects list `[p,n]` and returns list `[x^p,y^p]` as per specifications.

Explanation:

```
f(l)=[                      ,                     ]    Given a list, return a list
      floor(l[2]^{1/l})^l[1]                           floor(n^1/p)^p
                             ceil(l[2]^{1/l})^l[1]     ceil(n^1/p)^p

```
> 2 votes

# Answer
# Jelly, 8 bytes

```
*İ}Ḟ,ĊƊ*

```

Try it online!

Profoundly boring direct floor-ceil solution. However, if the N-is-a-power-of-P case can be relaxed to permit outputting just `[N]`...

# Jelly, 7 bytes

```
*İ}¹ị*€

```

Try it online!

...we actually have a builtin for floor-ceil. Namely, the index-into dyad .

```
*İ}        Pth root of N.
   ¹       (Break undesired initial 2,2,2 chain.)
    ị      Index that into
     *€    the list of x^P for all x <- 1..N.

```
> 2 votes

# Answer
# Desmos, 37 bytes

```
f(p,n)=[floor(k),ceil(k)]^p
k=n^{1/p}

```

Try It On Desmos!

Try It On Desmos! - Prettified

The best I could think of for now.
> 2 votes

# Answer
# 05AB1E, 8 bytes

```
zmDî‚ï¹m

```

Port of *@AidenChow*'s Desmos answer.

Inputs in the order \\$P,N\\$.

Try it online or verify all test cases.

**Explanation:**

$$\[N\_a,N\_b\]=\left\[\left\lceil N^\frac{1}{P}\right\rceil,\left\lfloor N^\frac{1}{P}\right\rfloor\right\]$$

```
z         # Push 1/P, where P is the first (implicit) input-integer
 m        # Take N to the power this 1/P, where N is the second (implicit) input-integer
  D       # Duplicate it
   î      # Ceil the copy
    ‚     # Pair the two together
     ï    # Floor/cast both to integers
      ¹m  # Take both values in the pair to the power P
          # (after which the resulting pair is output implicitly)

```
> 2 votes

# Answer
# Charcoal, 29 bytes

```
ＮθＮη≔¹ζＷ‹Ｘζθη≦⊕ζＩＸ⟦⁻ζ›Ｘζθηζ⟧θ

```

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

```
ＮθＮη

```

Input `P` and `N`.

```
≔¹ζ

```

Start with `y=1`.

```
Ｗ‹Ｘζθη≦⊕ζ

```

Increment `y` until it is large enough.

```
ＩＸ⟦⁻ζ›Ｘζθηζ⟧θ

```

Output the `P`th powers of `x` and `y`.

61 bytes for a more efficient version:

```
ＮθＮη≔¹ζ≔¹εＷ‹Ｘεθη≦⊗εＷ›⁻εζ¹«≔÷⁺εζ²ιＦ¬‹Ｘιθη≔ιεＦ¬›Ｘιθη≔ιζ»ＩＸ⟦ζε⟧θ

```

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

```
ＮθＮη

```

Input `P` and `N`.

```
≔¹ζ≔¹ε

```

Start with both `x` and `y` equal to `1`.

```
Ｗ‹Ｘεθη≦⊗ε

```

Double `y` until it is large enough.

```
Ｗ›⁻εζ¹«≔÷⁺εζ²ιＦ¬‹Ｘιθη≔ιεＦ¬›Ｘιθη≔ιζ»

```

Perform a binary search to narrow down the range of `x` and `y`.

```
ＩＸ⟦ζε⟧θ

```

Output the `P`th powers of `x` and `y`.

19 bytes using floating-point arithmetic:

```
Ｎθ≔ＸＩη∕¹θηＩＸ⟦⌊η⌈η⟧θ

```

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

```
Ｎθ

```

Input `P`.

```
≔ＸＩη∕¹θη

```

Take the `P`th root of `N`.

```
ＩＸ⟦⌊η⌈η⟧θ

```

Output the `P`th powers of the floor and ceiling.
> 1 votes

# Answer
# GolfScript, ~~25~~ ~~24~~ 23 bytes

```
{0\{@@).2$?.-1$<}do@;@}

```

Try it online!

I’m pretty sure this method is optimal, considering GolfScript doesn’t have floats and thus no min/max. ~~It’s possible that there’s a shorter way to do the stack manipulation, but that seems pretty unlikely to me at this point.~~ I stand corrected (by myself)—I was able to get rid of the variable `i`. Now I think this is optimal…but then I’ll probably find another 1-byte save somewhere else

This is a block (function) taking N then P on the stack and leaving the two values on top of the stack.

Explanation:

| Code | Stack (bottom to top) |
| --- | --- |
| `{…}` Block | `2 17` |
| `0\` | `2 0 17` |
| `{…}do` Run until result is 0… | Showing first pass over: |
| `@@` Stack shift | `17 2 0` |
| `)` Increment | `17 2 1` |
| `:` Duplicate | `17 2 1 1` |
| `2$` Push third from stack | `17 2 1 1 2` |
| `?` Exponentiate | `17 2 1 2` |
| `:` Duplicate | `17 2 1 2 2` |
| `-1$` Push bottom of stack | `17 2 1 2 2 17` |
| `<` Less than? | `-1 2 1 2 0` |
| (pop and either repeat or stop) | `17 2 1 2` |

At the end of the loop, the stack looks like `17 1 4 9 16 2 5 25` so we do `@;@` to make the top of the stack be `25 16`.

It took like twenty minutes of fiddling around to get the stack manipulation to work right.
> 1 votes

# Answer
# C#, 79 bytes

```
(p,n)=>(Math.Pow(Math.Pow(n,1d/p)is{}x?(int)x:x,p),Math.Pow(Math.Ceiling(x),p))

```

Alternate approach that uses 87 bytes

```
(p,n)=>{var(i,x)=(0,0d);for(;(x=Math.Pow(++i,p))<n;);return(Math.Pow(x==n?i:~-i,p),x);}

```

Try it online!
> 1 votes

# Answer
# APL+ WIN, 18 bytes

Prompts for power and integer:

```
((⌊p),⌈p←⎕*÷n)*n←⎕

```

Try it online! Thanks to Dyalog Classic
> 1 votes

# Answer
# MATL, 14 bytes

```
w1Y\^tkwXkh1G^

```

Try on MATL Online or Test all cases

```
w    % Get both inputs and bring P to the top of the stack
1Y\  % Take the inverse of P
^    % Raise N to that power i.e. take N's P-th root
tk   % Take a copy of that root and floor it
wXk  % And ceil the original copy
h1G^ % Raise both those values to the power of P

```
> 1 votes

# Answer
# Vyxal 3, 7 bytes

```
ė*∦⌊⌈$*

```

Try it Online!

Takes two integers as its argument and returns two integers. Works the same as various other answers including @mathscat’s Vyxal one and @UnrelatedString’s Jelly one.

## Explanation

ė*∦⌊⌈$*
ė       | Reciprocal of n
 *      | To the power of p
  ∦⌊⌈   | Pair ceiling with floor and wrap in a list
     $* | To the power of p

```
</code></pre>
> 1 votes

# Answer
# Rust, ~~67~~ 66 bytes

```
|p,n:f64|{let x=n.powf(1./p);(x.floor().powf(p),x.ceil().powf(p))}

```

Try it online!

Trivial implementation: takes `n` to the power of `1/p`, and then calculates `floor` and `ceil` to the power of `p`.

Takes the integer inputs as 64-bit floats and returns its output as a tuple of 64-bit floats.

*-1 byte thanks to ceilingcat*
> 1 votes

---
Tags: code-golf, math, integer
---


title: Bingo Cards PDF

text:
# Question
Title: Bingo Cards PDF
Write code to generate a PDF file containing 6 bingo cards. Winner is the one that uses the shortest code and needs no actions except for installing a library and running the code. (No Save As PDF). Rules are as follows.

* The generated PDF file should display accurately in Adobe's PDF reader, Google Chrome and Moxilla Firefox.
* Page size should be either Letter or A4.
* Cards should be arranged in 3 rows and 2 columns.
* Each card should be 3 inches in width and height.
* Each card should contain numbers 1 to 25 in random order, arranged in 5x5 squares. The numbers in all 6 cards should be generated independently.
* Text size should be 20 points.
* Text font should be Helvetica, Arial, Calibri or Open Sans. Text should be centered in each cell.
* The bingo cards should have borders with lines having thickness either 0.5 or 1 points.
* You can use a pre-existing, publicly available library or package to create a PDF file but the code to generate and arrange bingo cards should be your own.
* These is a margin of 20% allowed in each dimension, but all cards should be strictly equal in size.

# Reference Answer

Install `reportlab` using `pip install reportlab`

```
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import letter
from random import shuffle
my_canvas = canvas.Canvas("Bingo Cards.pdf", pagesize=letter)
my_canvas.setLineWidth(1)
my_canvas.setFont('Helvetica', 20)
a = [i for i in range(1, 26)]
for row in range(0, 3):
    for col in range (0, 2):
        shuffle(a)
        rowplace = 252*row
        colplace = 276*col
        my_canvas.line(60+colplace, 36+rowplace, 276+colplace, 36+rowplace)
        my_canvas.line(276+colplace, 36+rowplace, 276+colplace, 246+rowplace)
        my_canvas.line(60+colplace, 36+rowplace, 60+colplace, 246+rowplace)
        my_canvas.line(60+colplace, 246+rowplace, 276+colplace, 246+rowplace)
        for grid in range(0, 5):
            gridplace = grid*43.2
            my_canvas.line(60+colplace, 36+rowplace+gridplace, 276+colplace, 36+rowplace+gridplace)
            my_canvas.line(60+colplace+gridplace, 36+rowplace, 60+colplace+gridplace, 246+rowplace)
            for i in range(0, 5):
                my_canvas.drawCentredString(81.6+colplace+gridplace, 47.6+rowplace+i*43.2, str(a[i+5*grid]))
my_canvas.save()

```

The result is shown in the following image.

# Answer
# Python 3.8 (pre-release), 380 bytes

Requires `reportlab`. Install `reportlab` using `pip install reportlab`.

Default A4 pagesize, the margin on the dimensions allows for the rounding on the cards' positions.

Save the pdf file as "b".

```
from reportlab.pdfgen import canvas
import random
b=canvas.Canvas('b')
b.setLineWidth(1)
b.setFont('Helvetica',20)
n=list(range(25))
w=216
d=43
for y in(48,313,577):
 for x in(54,325):
  random.shuffle(n);b.lines([(x,y,x+w,y),(x,y,x,y+w)])
  for i in range(25):f,g=x+d*(i%5),y+d*(i//5);b.lines([(x,g+d,x+w,g+d),(f+d,y,f+d,y+w)]);b.drawCentredString(f+22,g+12,str(n[i]+1))
b.save()

```

---

# Python 3.8 (pre-release), fully parametrized, 551 bytes

Default A4 pagesize. All the dimensions are parametrized:

* font size
* numbers in each card
* number of cards in the page, arranged in rows and columns
* size of card

Save the pdf file as "b".

```
from reportlab.pdfgen import canvas
from reportlab.lib.units import inch
import random
b=canvas.Canvas('b')
b.setLineWidth(1)
t=20
b.setFont('Helvetica',t)
k=25
q=int(k**.5)
n=list(range(k))
r=3
c=2
w=3*inch
h=3*inch
d=w/q
e=h/q
o=(b._pagesize[0]-w*c)/(c+1)
v=(b._pagesize[1]-h*r)/(r+1)
for y in range(r):
 y=y*(v+h)+v
 for x in range(c):
  x=x*(o+w)+o;random.shuffle(n);b.lines([(x,y,x+w,y),(x,y,x,y+h)])
  for i in range(k):f,g=x+d*(i%q),y+e*(i//q);b.lines([(x,g+e,x+w,g+e),(f+d,y,f+d,y+h)]);b.drawCentredString(f+d/2,g+(e-t)/2,str(n[i]+1))
b.save()

```

---

*Code with comments*

```
from reportlab.pdfgen import canvas
from reportlab.lib.units import inch
import random

# pdf canvas, default A4
b=canvas.Canvas('b')
b.setLineWidth(1)

t=20
b.setFont('Helvetica',t)

# numbers in each card
k=25
# numbers in cards are arranged in perfect squares
q=int(k**.5)
n=list(range(k))

# cards in page, arranged in rows and columns
r=3
c=2

# width and height of cards
w=3*inch
h=3*inch

# size of cells
d=w/q
e=h/q

# spacing between cards
o=(b._pagesize[0]-w*c)/(c+1)
v=(b._pagesize[1]-h*r)/(r+1)

# loop on rows in page
for y in range(r):

    # bottom position of card
    y=y*(v+h)+v

    # loop on columns in page
    for x in range(c):

        # left position of card
        x=x*(o+w)+o

        # randomize numbers
        random.shuffle(n)

        # draw the bottom and left line of card
        b.lines([(x,y,x+w,y),(x,y,x,y+h)])

        # loop on numbers
        for i in range(k):

            # orizontal and vertical position of the lines
            # as offset from the initial position of the card
            f,g=x+d*(i%q),y+e*(i//q)

            # draw lines
            b.lines([(x,g+e,x+w,g+e),(f+d,y,f+d,y+h)])

            # draw number as text, centered in the cell
            b.drawCentredString(f+d/2,g+(e-t)/2,str(n[i]+1))

# save pdf canvas as file
b.save()

```
> 2 votes

---
Tags: code-golf, card-games, file-system
---