18
\$\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:

BERJAYA

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 BERJAYA
600, 1000, 0.7 BERJAYA
800, 800, 0.9 BERJAYA
500, 900, 1 BERJAYA
700, 1200, 0.6 BERJAYA
200, 250, 0.3 BERJAYA
\$\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 2 days ago
  • 1
    \$\begingroup\$ @UnrelatedString Which is precisely why I chose it (the moiré, not the burning) :-D \$\endgroup\$ – Luis Mendo 2 days ago
  • 1
    \$\begingroup\$ @pxeger I didn't know that, sorry. Go ahead then. Any ouput format that has consensus is fine \$\endgroup\$ – Luis Mendo 2 days ago
  • 7
    \$\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 2 days ago
  • 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 2 days ago

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 2 days ago
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

New contributor
Danica Scott is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.
\$\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 yesterday
  • 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 yesterday
  • 2
    \$\begingroup\$ Technically you need range(1,R+1) and range(1,C+1), though that's likely golfable \$\endgroup\$ – Tipping Octopus yesterday
  • 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 yesterday
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\$
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 yesterday
  • \$\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 yesterday
  • \$\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 yesterday
  • 1
    \$\begingroup\$ 66 bytes but I posted this one myself! \$\endgroup\$ – Dominic van Essen yesterday
2
\$\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]

New contributor
Alwin is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.
\$\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 11 hours ago
  • \$\begingroup\$ Thank you for teaching me something new! That is amazing. \$\endgroup\$ – Alwin 11 hours ago
1
\$\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 yesterday
  • \$\begingroup\$ @LuisMendo Indeed :) \$\endgroup\$ – Galen Ivanov yesterday

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.