Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

Intro

Something I've played around with in recreational mathematics has been construction of a divisor table to visually compare/contrast the prime divisors of a set of numbers. The set of input numbers are across the top as column labels, the prime divisors are on the left as row labels, and a mark indicates where the two line up.

For example, for input 6, 9, 14, 22 a table similar to the following would be constructed:

    6  9 14 22
 2  *     *  *
 3  *  *
 7        *
11           *

This is because 6 has prime divisors of 2 and 3, 9 has prime divisors of 3, and so on.

Construction

  • The table is constructed such that the input numbers form column labels that are separated by spaces and in ascending order (you can assume they are pre-sorted), and the prime divisors are listed on the left in ascending order one per line forming the row labels.
  • Note that leading spaces on the prime divisors and input numbers may be required if the numbers are different lengths, so that all columns are the same width and line up appropriately.
  • Each divisor is represented by a single * (or other suitable ASCII character of your choosing, so long as the same character is used for all occurrences).
  • Multiple divisors are ignored (e.g., 3 x 3 = 9 but there's only one * for that intersection).
  • The * can be placed anywhere horizontally in the column, so long as it's unambiguous (I have all my examples with the * right-aligned).

Input

  • A list of positive integers in any convenient format, each >1.
  • You can assume that the input is pre-sorted.
  • The input is guaranteed to have only unique values.

Output

The resulting ASCII art representation of the prime divisor table.

Rules

  • Leading or trailing newlines or whitespace are all optional, so long as the characters themselves line up correctly.
  • Either a full program or a function are acceptable. If a function, you can return the output rather than printing it.
  • If possible, please include a link to an online testing environment so people can try out your code!
  • Standard loopholes are forbidden.
  • This is so all usual golfing rules apply, and the shortest code (in bytes) wins.

Examples

6,9,14,22

    6  9 14 22
 2  *     *  *
 3  *  *
 7        *
11           *


2,3,5,7

  2 3 5 7
2 *
3   *
5     *
7       *

2,4,8,16,32

   2  4  8 16 32
2  *  *  *  *  *

75,99,151,153

     75  99 151 153
  3   *   *       *
  5   *
 11       *
 17               *
151           *
share|improve this question
1  
Can we have divider lines after the top row and the left column? – ngenisis 12 hours ago

Mathematica, 101 bytes

Grid[p=Prepend;Thread[q[Outer[If[#∣#2,Y,""]&,f=#&@@@FactorInteger[1##],g={##}]~p~g,f~p~""]]/.q->p]&

The character about a third of the way through is U+2223 (3 bytes). Unnamed function of a variable number of arguments, each of which is a nonzero integer, which returns a Grid object (formatted output) like so:

Grid object output

f=#&@@@FactorInteger[1##] defines f to be the set of all primes dividing any of the inputs (equivalently, dividing their product 1##), while g is the list consisting of the inputs. Outer[If[#∣#2,Y,""]&,f,g] makes a table of Ys and empty strings corresponding to divisibility (we use the undefined token Y instead of a string "Y" or "*" to save two bytes). Then we prepend the row and column headers thereon, using Thread at one point to map a prepend operation over two lists for the row headers. In that step, using p too soon seems to break the process, so we use an undefined token q at first and then change it to p after the threading is done.

share|improve this answer
    
You can leave out the first "". – Martin Ender 12 hours ago
1  
TableForm[Outer[If[#∣#2,Y,""]&,f=#&@@@FactorInteger[1##],g={‌​##}],TableHeadings->‌​{f,g}]& if dividers are allowed – ngenisis 12 hours ago
    
And the second as well if you change it to p[f,]. – Martin Ender 12 hours ago

Jelly, 25 23 bytes

PÆfQ©ḍþµị⁾* ³;"Z⁶;®¤;"G

Try it online!

How?

It may well be shorter to use ÆE and filter out empty rows.

PÆfQ©ḍþµị⁾* ³;"Z⁶;®¤;"G - Main link: list of numbers, L
       µ                - monadic chain separation
P                       - product of L - multiply them all together
 Æf                     - prime factors (with repetitions, in ascending order)
   Q                    - unique items, maintaining order
                              - note that the product was performed to keep order
    ©                   - place in the register for later use, and yield
      þ                   - form the outer product of that and L using the dyad:
     ḍ                  -     isDivisor - 1 if divides, 0 if not
        ị⁾* <space      - index into "* " (1s to "*", 0s to " ")
            ³           - program's first input, L
             ;"         - zip with concatenation (column headers to the left)
               Z        - transpose (get it around the right way)
                   ¤    - nilad followed by link(s) as a nilad
                ⁶;®     - space (⁶) concatenated with (;) the register value (®)
                    ;"  - zip with concatenation (row labels to the left)
                      G - format the result as a grid (join items with spaces and
                                               rows with line feeds so they align)
                        - implicit print
share|improve this answer

Jelly, 18 bytes

PÆfQ0;ðḍ€+W}⁸;"o⁶G

Uses 1 instead of *, as allowed by the rules.

Try it online!

How it works

PÆfQ0;ðḍ€+W}⁸;"o⁶G  Main link. Argument: A (array of integers greater than 1)

P                   Take the product of the integers in A.
 Æf                 Compute all prime factors (with multiplicity) of the product.
   Q                Unique; deduplicate the prime factors.
    0;              Prepend a 0. Let's call the result P.
      ð             Begin a new, dyadic chain. Left argument: P. Right argument: A
       ḍ€           Divisible each; for each p in P, test all integers in A for
                    divisibility by P. Yields one row of the shape of A for each p.
                    Note that the first element of P is 0, so the first row of the
                    resulting matrix contains only zeroes.
          W}        Wrap right; yield [A].
         +          Add the results to both sides. Because of how Jelly's auto-
                    vectorization works, this adds the first row of [A] (just A) to
                    the first row of the divisibility matrix (all zeroes) and
                    leaves the other rows untouched.
            ⁸;"     Prepend the elements of P to the corresponding rows of the
                    previous result.
               o⁶   OR space; replace all zeroes with spaces.
                 G  Grid; format the matrix as requested in the challenge spec.
share|improve this answer
    
¿Puedo tener explicación por favor? ([May] I have an explanation please?) – R. Kap 5 hours ago
    
@R.Kap I've added an explanation. – Dennis 3 hours ago

Mathematica, 165 bytes

Rather verbose - maybe someone can do something with it:

(j=Join;a=#[[All,1]]&/@FactorInteger@#;b=Sort@DeleteDuplicates@Flatten@a;Grid[j[{j[{""},#]},Transpose@j[{b},Table[If[MemberQ[a[[t]],#],"*",""]&/@b,{t,Length@a}]]]])&
share|improve this answer

Bash + GNU utilities, 134 bytes

q=printf\ ;$q%9s;$q%9d $@;echo;for p in `factor $@|tr \  '\n'|grep -v :|sort -un`;{ $q%9d $p;for x;{ c=X;((x%p))&&c=;$q%9s $c;};echo;}

Try it online!

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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