19
\$\begingroup\$

Let \$R, C\$ be positive integers and let \$0 < s \leq 1\$. Consider the \$R \times C\$ matrix \$\mathbf M\$ defined as \begin{equation} M(i,j) = \frac{\mathrm{mod}\,(j, i^s)}{R^s}, \quad i = 1, \ldots, R, \quad j = 1, \ldots, C \end{equation} where \$\,\mathrm{mod}\,\$ denotes the modulo operation: for \$a,b > 0\$ not necessarily integer, \$\mathrm{mod}\,(a,b) = c\$ if and only if \$0 \leq c < b\$ and \$a = b\cdot k + c\$ with \$k\$ integer.

Note that \$0 \leq M(i,j) < 1\$.

The matrix \$\mathbf M \$ can be displayed as an image, where the value of each entry determines the color of a pixel, using a colormap to translate numbers between \$0\$ and \$1\$ into colors. The simplest colormap is to directly consider each number as grey intensity, with \$0\$ corresponding to black and \$1\$ to white.

As an example, \$R=500\$, \$C=800\$, \$s=0.8\$ with the grey colormap give the following image:

The challenge

Given two positive integers \$100 \leq R, C \leq 2000 \$ and a number \$0 < s \leq 1\$, display the above defined matrix \$\mathbf M\$ as an image. You can use any colormap of your choice, not necessarily consistent across images, as long as it satisfies the very lax requirements described next.

Colormap requirements

  1. At least \$16\$ different colours.
  2. Reasonably gradual changes between adjacent colours.
  3. The first and last colours should be clearly different.

Although the terms reasonably gradual and clearly different are somewhat subjective, this is not likely to be a contentious point. The sole purpose of these requirements is to prevent abuse. If your programming language offers a default colormap, it is most likely fine. If it doesn't, using grey is probably the shortest option.

Additional rules

  • Graphical output is required, with output being flexible as usual.
  • The image should have the correct orientation, with \$M(1,1)\$ corresponding to the upper-left corner.
  • The image should have the aspect ratio given by \$R\$ and \$C\$. That is, each entry of \$\mathbf M\$ should correspond to a square pixel.
  • If the image is output by displaying it on the screen, it is not necessary that each screen pixel corresponds to an image pixel. That is, the display scaling is flexible (but the aspect ratio should be kept).
  • Auxiliary elements such as axis labels, grid lines or a white frame are not required, but are allowed.
  • Programs or functions are accepted. Standard loopholes are forbidden.
  • Shortest code in bytes wins.

Test cases

Each of the following uses a different colormap, to illustrate some possibilities (and not incidentally to produce lively pictures).

Inputs: R, C, s Output
500, 800, 0.8
600, 1000, 0.7
800, 800, 0.9
500, 900, 1
700, 1200, 0.6
200, 250, 0.3
\$\endgroup\$
13
  • 3
    \$\begingroup\$ I just want to say that the last example output has some very interesting moirés once your eyes stop burning \$\endgroup\$ – Unrelated String Jul 7 at 15:57
  • 1
    \$\begingroup\$ @UnrelatedString Which is precisely why I chose it (the moiré, not the burning) :-D \$\endgroup\$ – Luis Mendo Jul 7 at 15:58
  • 1
    \$\begingroup\$ @pxeger I didn't know that, sorry. Go ahead then. Any ouput format that has consensus is fine \$\endgroup\$ – Luis Mendo Jul 7 at 16:00
  • 8
    \$\begingroup\$ What part of this did you consider the "meat" of the challenge while writing it? If a matrix is OK, it seems like it boils down to two loops/ranges and the formula j%i^s/r^s verbatim from the post, which does not look like it admits much clever tricks. If the output is PGM then there's a bit more to golf. So, I want to make sure that permitting matrix output doesn't water down your vision for this challenge. \$\endgroup\$ – Lynn Jul 7 at 17:15
  • 2
    \$\begingroup\$ @Lynn Graphical output was (is) an important part of the challenge. Just outputting a matrix waters it down, yes. But that doesn't seem to be allowed by the meta post about image formats. Admittedly there are formats that are close to just the matrix, but they have to be accepted \$\endgroup\$ – Luis Mendo Jul 7 at 17:57

10 Answers 10

6
\$\begingroup\$

Haskell, 131 bytes

f=fromIntegral
u=unwords.map show
a%b|a>b=(a-b)%b|1<2=a
(r#c)s="P2":u[c,r,99]:[u[round$f j%(f i**s)/f r**s*99|j<-[1..c]]|i<-[1..r]]

Try it online!

(r#c)s returns the lines of a PGM file.

After writing it like this, I learned I could probably just return a matrix of float values but I don't think that's very interesting.

enter image description here

\$\endgroup\$
1
  • \$\begingroup\$ Allowed formats are the ones with consensus here. Outputting just the matrix is not one of thoese formats, I think \$\endgroup\$ – Luis Mendo Jul 7 at 17:59
6
\$\begingroup\$

J, 51 bytes

load'viewmat'
1 :'[:viewmat(|~^&u)"0~/&(1+i.)%u^~['

Try it online!

A J adverb, which uses the library function viewmat to do all the heavy lifting -- we merely need to construct the matrix values.

Assuming the adverb has been assigned to f, called like:

500 (0.8 f) 800

500 800 0.8

500 800 0.8

200 250 0.3

200 250 0.3

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

Wolfram Language (Mathematica), 39 bytes

sImage@Array[Mod[#2,#^s]&,{##}]/#^s&

Try it online!

Input [s][R, C].

Test cases run in Mathematica

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

K (oK) + iKe, 61 bytes

{w::y;h::x;p::pow[;z];,(;gray;+_255*((p 1+!h)!\:/:1+!w)%p w)}

Try it online!

Shortened heavily and made to work with the help of JohnE and coltim at the k tree.

A function which takes input as R, C, s.

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

Python 3, 116 114118 bytes

-2 thanks to some basic pointers from hyper-neutrino
+4 to correct an off-by-one error, thanks Tipping Octopus

from matplotlib.pylab import*
def M(R,C,s):
 imshow([[j%i**s/R**s for j in range(1,C+1)]for i in range(1,R+1)]);show()

Fairly straightforward, my first code golf attempt so I may be missing something easily golfable. Executes nested list comprehension inside the imshow() to immediately create image. Needs the show() to actually display the image.

700, 1200, 0.6

700, 1200, 0.6

\$\endgroup\$
4
  • 2
    \$\begingroup\$ Welcome to Code Golf Stack Exchange! If you move the import out of the function, you can save a byte for the indentation. Also, you can inline statements within a function by putting them on one line and separating them with semicolons, which saves more indentation. \$\endgroup\$ – hyper-neutrino Jul 8 at 2:53
  • 1
    \$\begingroup\$ @hyper-neutrino thanks for the tips! I had assumed the import statement needed to be inside the function definition, but it's good that it doesn't! \$\endgroup\$ – Danica Scott Jul 8 at 3:43
  • 2
    \$\begingroup\$ Technically you need range(1,R+1) and range(1,C+1), though that's likely golfable \$\endgroup\$ – Tipping Octopus Jul 8 at 5:28
  • 1
    \$\begingroup\$ You can golf it a bit more with: def f(R,C,s):imshow([[-~j%i**s/R**s for j in range(C)]for i in range(1,R+1)]);show() \$\endgroup\$ – Noodle9 Jul 8 at 11:19
4
\$\begingroup\$

JavaScript + HTML, 156 bytes

(R,C,s)=>{for((w=x=>document.write(x))`<table cellspacing=0>`,i=0;i++<R;)for(w`<tr>`,j=0;j<C;)w(`<td bgcolor=#${((++j%i**s*16/R**s|0)*273).toString(16)}>`)}
  • -7 bytes by Shaggy

; (function run() {

f=

(R,C,s)=>{for((w=x=>document.write(x))`<table cellspacing=0>`,i=0;i++<R;)for(w`<tr>`,j=0;j<C;)w(`<td bgcolor=#${((++j%i**s*16/R**s|0)*273).toString(16)}>`)}

R = /*R{*/500/*}*/;
C = /*C{*/800/*}*/;
s = /*s{*/0.8/*}*/;

document.write(`
<div style="margin-bottom: 10px;">
  <label> R = <input id="inputR" type="number" step="1" value="${R}" oninput="UpdateJS()" /></label><br />
  <label> C = <input id="inputC" type="number" step="1" value="${C}" oninput="UpdateJS()" /></label><br />
  <label> s = <input id="inputS" type="number" step="0.01" value="${s}" oninput="UpdateJS()" /></label><br />
  <form action="${location.href}" method="post">
    <input id="inputJs" type="hidden" name="js" />
    <input type="hidden" name="css" />
    <input type="hidden" name="html" />
    <input type="hidden" name="console" value="false" />
    <input type="hidden" name="babel" value="false" />
    <button type="submit">Draw</button>
  </form>
</div>
`)

f(R, C, s);

UpdateJS = function () {
  R = inputR.value;
  C = inputC.value;
  s = inputS.value;
  js = `; (${run}());`
    .replace(/\/\*R\{\*\/.*?\/\*\}\*\//, `/*R{*/${R}/*}*/`)
    .replace(/\/\*C\{\*\/.*?\/\*\}\*\//, `/*C{*/${C}/*}*/`)
    .replace(/\/\*s\{\*\/.*?\/\*\}\*\//, `/*s{*/${s}/*}*/`);
  inputJs.value = js;
};

UpdateJS();

}());

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

R, 66 bytes

function(R,C,s)cat('P2',C,R,99,(99*outer(1:C,(1:R)^s,`%%`))%/%R^s)

Try it online!

I kinda think that pajonk's answer is close to the shortest possible using R's built-in graphics... so here's a completely different approach, which actually turns-out to be 4 bytes shorter...

Outputs the contents of a greyscale PGM file. At least on my laptop using Apple's 'Preview' program, the newline characters separating lines appear to be superfluous.

Here's Preview's display of the the output of ploughed_field(500,800,.8):

enter image description here

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

Python 3, 90 73 bytes

from pylab import*;ion()
def M(R,C,s):imshow(-~r_[:C]%c_[1:R+1]**s/R**s)

Heavily based on Danica's answer, I would have commented but I have 0 reputation.

Shorter import statement

ion() to show instead of ;show()

arange (from numpy.arange) array approach for faster performance and fewer bytes

remove def function indent

   from pylab import* 
   ion()
   def M(R,C,s):imshow((arange(C)+1)%(arange(R)+1)[:,None]**s/R**s)

Thanks to ovs this shortens to 74 bytes

And a -~ trick removes 1 byte from r_[1:C+1]

\$\endgroup\$
2
  • 2
    \$\begingroup\$ Welcome to CGCC! numpy has the builtins r_ and c_, which concatenate arrays and slices along different axis. In this case, they can be used to shorten the expression to r_[1:C+1]%c_[1:R+1]**s/R**s \$\endgroup\$ – ovs Jul 9 at 11:20
  • \$\begingroup\$ Thank you for teaching me something new! That is amazing. \$\endgroup\$ – Alwin Jul 9 at 11:34
3
\$\begingroup\$

R, 84 70 bytes

-14 bytes thanks to @Dominic

function(R,C,s)image(outer(1:C,(R:1)^s,`%%`)/R^s,c=rainbow(64),as=R/C)

Try it online!

Try it on rdrr.io with graphical output

\$\endgroup\$
4
  • 1
    \$\begingroup\$ 70 bytes... \$\endgroup\$ – Dominic van Essen Jul 8 at 9:49
  • \$\begingroup\$ (or an even more brightly-coloured version for 69 bytes - unless there are possible inputs with R<16 but that still need ≥16 colours)... \$\endgroup\$ – Dominic van Essen Jul 8 at 10:00
  • \$\begingroup\$ Hm. Please ignore the 69-byter: there are lots of possible inputs with R<16 that need many more colours... \$\endgroup\$ – Dominic van Essen Jul 8 at 10:12
  • 1
    \$\begingroup\$ 66 bytes but I posted this one myself! \$\endgroup\$ – Dominic van Essen Jul 8 at 14:09
2
\$\begingroup\$

Red, 137 bytes

func[r c s][i: make image! to[]as-pair c r k: 0
repeat y r[repeat x c[i/(k: k + 1): to 1.1.1 to[](to 1 x %(y ** s)/(r ** s)* 255)]]?(i)]	

f 500 800 0.8

enter image description here

\$\endgroup\$
2
  • 3
    \$\begingroup\$ Very appropriate colormap for a Red answer :-D \$\endgroup\$ – Luis Mendo Jul 8 at 14:51
  • \$\begingroup\$ @LuisMendo Indeed :) \$\endgroup\$ – Galen Ivanov Jul 8 at 18:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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