ASCII rhombic grid

27

1

Write the shortest code measured by byte count to generate an ASCII grid composed of rhombi, given the following parameters:

  • m - number of complete rhombi in one row
  • n - number of rows
  • s - side of the smallest rhombus
  • r - level of nesting - how many rhombi are there inside the "base ones" (which are fonud between the intersections of the grid)

Examples

1. Input: 5 3 1 0
Output:

/\/\/\/\/\
\/\/\/\/\/
/\/\/\/\/\
\/\/\/\/\/
/\/\/\/\/\
\/\/\/\/\/

A 5x3 grid of rhombi with side 1, no nesting

2. Input: 3 2 2 0
Output:

 /\  /\  /\
/  \/  \/  \
\  /\  /\  /
 \/  \/  \/ 
 /\  /\  /\
/  \/  \/  \
\  /\  /\  /
 \/  \/  \/ 

A 3x2 grid of rhombi with side 2, no nesting

3. Input: 5 2 1 2
Output:

///\\\///\\\///\\\///\\\///\\\
///\\\///\\\///\\\///\\\///\\\
///\\\///\\\///\\\///\\\///\\\
\\\///\\\///\\\///\\\///\\\///
\\\///\\\///\\\///\\\///\\\///
\\\///\\\///\\\///\\\///\\\///
///\\\///\\\///\\\///\\\///\\\
///\\\///\\\///\\\///\\\///\\\
///\\\///\\\///\\\///\\\///\\\
\\\///\\\///\\\///\\\///\\\///
\\\///\\\///\\\///\\\///\\\///
\\\///\\\///\\\///\\\///\\\///

A 5x2 grid of rhombi with side 1 (the smallest rhombus), level of nesting is 2

4. Input: 4 2 2 1
Output:

 //\\  //\\  //\\  //\\ 
///\\\///\\\///\\\///\\\
//  \\//  \\//  \\//  \\
\\  //\\  //\\  //\\  //
\\\///\\\///\\\///\\\///
 \\//  \\//  \\//  \\//   
 //\\  //\\  //\\  //\\ 
///\\\///\\\///\\\///\\\
//  \\//  \\//  \\//  \\
\\  //\\  //\\  //\\  //
\\\///\\\///\\\///\\\///
 \\//  \\//  \\//  \\//   

A 4x2 grid of rhombi with side 2 with level of nesting 1 

5. Input: 4 2 3 3
Output:

  ////\\\\    ////\\\\    ////\\\\    ////\\\\
 /////\\\\\  /////\\\\\  /////\\\\\  /////\\\\\
//////\\\\\\//////\\\\\\//////\\\\\\//////\\\\\\
//////\\\\\\//////\\\\\\//////\\\\\\//////\\\\\\
/////  \\\\\/////  \\\\\/////  \\\\\/////  \\\\\
////    \\\\////    \\\\////    \\\\////    \\\\
\\\\    ////\\\\    ////\\\\    ////\\\\    ////
\\\\\  /////\\\\\  /////\\\\\  /////\\\\\  /////
\\\\\\//////\\\\\\//////\\\\\\//////\\\\\\//////
\\\\\\//////\\\\\\//////\\\\\\//////\\\\\\//////
 \\\\\/////  \\\\\/////  \\\\\/////  \\\\\/////  
  \\\\////    \\\\////    \\\\////    \\\\////  
  ////\\\\    ////\\\\    ////\\\\    ////\\\\
 /////\\\\\  /////\\\\\  /////\\\\\  /////\\\\\
//////\\\\\\//////\\\\\\//////\\\\\\//////\\\\\\
//////\\\\\\//////\\\\\\//////\\\\\\//////\\\\\\
/////  \\\\\/////  \\\\\/////  \\\\\/////  \\\\\
////    \\\\////    \\\\////    \\\\////    \\\\
\\\\    ////\\\\    ////\\\\    ////\\\\    ////
\\\\\  /////\\\\\  /////\\\\\  /////\\\\\  /////
\\\\\\//////\\\\\\//////\\\\\\//////\\\\\\//////
\\\\\\//////\\\\\\//////\\\\\\//////\\\\\\//////
 \\\\\/////  \\\\\/////  \\\\\/////  \\\\\/////  
  \\\\////    \\\\////    \\\\////    \\\\////  

A 4x2 grid of rhombi with side 3, level of nesting 3

Be sure to display the partially visible rhombi at the edges and corners where necessary.

Galen Ivanov

Posted 2017-10-31T16:35:05.297

Reputation: 13 815

1@AdmBorkBork By "nesting" I mean the number of rhombi inscribed in the base ones, found between the intersections of the grid. – Galen Ivanov – 2017-10-31T17:19:41.353

3Related – Luis Mendo – 2017-10-31T17:46:36.563

@Luis Mendo - yes, it's clearly related to my task. – Galen Ivanov – 2017-10-31T18:18:54.053

@Stewie Griffin: https://codegolf.stackexchange.com/questions/146747/ascii-rhombic-grid#comment359169_146747 — 3rd test case

– sergiol – 2017-11-01T00:29:01.183

5Oh, how I miss my pillow! – Stewie Griffin – 2017-11-01T08:23:54.447

Answers

17

SOGL V0.12, 20 bytes

ā.I∫e+H╚╬8}:±№╬8╬¡∙*

Try it Here! Takes the input in the reversed order of what they are in the examples - r, s, n, m.

Explanation:

ā                     push an empty array - canvas
 .I∫      }           for each in range(input) (1-indexed)
    e+                  add the second input
      H                 decrement
       ╚                create a diagonal of that size
        ╬8              insert into the canvas
           :          create a duplicate of the canvas
            ±№        reverse it vertically and horizotally
              ╬8      insert that into the canvas
                έ    quad-palindromize
                  ∙   multiply vertically by the next input
                   *  multiply horizontally by the next input

dzaima

Posted 2017-10-31T16:35:05.297

Reputation: 19 048

2This is just amazing, how do you even compress such a program in 20 bytes. – Erik the Outgolfer – 2017-10-31T17:45:57.390

1This is just brilliant... +1 from me for beating Charcoal by a staggering 28 bytes :O – Mr. Xcoder – 2017-10-31T18:05:28.593

That''s really impressive! – Galen Ivanov – 2017-10-31T18:28:52.133

@Mr.Xcoder 19 bytes now. But then I'm up against builtins like ∙*... – Neil – 2017-10-31T19:57:20.763

@Neil * is basically vercorized repetition, and - non-vectorized repetition. Those two built-ins together should be <=4 bytes in many golfing languages – dzaima – 2017-10-31T20:06:39.717

1Vectorised string repeating is reasonably short in Charcoal; if I could build up a string representation of the diamond it would only cost me 6 bytes to repeat it. Unfortunately it takes me 50 bytes to do that. On the other hand, drawing the diamond only takes me 17 bytes, just 1 more than SOGL... but it then takes 20 bytes to multiply the canvas. – Neil – 2017-11-01T10:26:36.303

@neil I had a feeling it was like that. I'm guessing that Charcoal can't get the canvas as a single string? – dzaima – 2017-11-01T11:23:01.690

8

Python 2, 160 159 158 bytes

-1 byte thanks to Jonathan Frech

m,n,s,r=input()
l=~-s*' '+'/'*(r-~r)+~-s*' '
for x in range(n*2):print'\n'.join(m*(l[i:i+s+r]+l.replace(*'/\\')[i:i+s+r][::-1])for i in range(r+s))[::1-x%2*2]

Try it online!

This uses the fact that the bottom of the rhombus is the top inverted ([::-1]), iterating over range(n*2) and using ~x%2*2-1 to control if it is the top or the bottom.
For the top (and the bottom) the right side is just the left side inverted and replacing / with \ -> l.replace(*'/\\')..[::-1]
To generate the pattern / nesting ~-s*' '+'/'*(1+r*2)+~-s*' ' is used to make a string like /// that will be iterated and chopped :

   '|  //|/  '  
  ' | ///|  '  
 '  |/// | '  
'  /|//  |'  

Rod

Posted 2017-10-31T16:35:05.297

Reputation: 17 588

I think (1+r*2) can be (r-~r). – Jonathan Frech – 2017-11-01T23:39:24.240

8

Charcoal, 48 39 37 bytes

UO⊕Iε\F⊖IζC¹¦¹‖ML≔⊗⁺IζIεδF⊖NCδ⁰F⊖NC⁰δ

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

UO⊕Iε\

Draw a square of size r + 1. This is a quarter of a nested diamond of size 1.

F⊖IζC¹¦¹

Copy the square 1 square right and down s - 1 times to get it to the right size.

‖ML

Reflect it to become a full nested diamond.

≔⊗⁺IζIεδ

Compute the size of this nested diamond.

F⊖NCδ⁰

Copy the diamond to the right m - 1 times.

F⊖NC⁰δ

Copy the diamond downwards n - 1 times.

Neil

Posted 2017-10-31T16:35:05.297

Reputation: 95 035

7

Julia 0.6, 190 bytes

g(n,m,s,r)=(s+=r+1;f(i,j,u=mod(i-j+r,2s),v=mod(j+i+r,2s))=(" \\/")[abs(u-r)<abs(v-r)?1+(u<=2r):1+2(v<=2r)];
for i=1:2(s-1)m println((f(i+(i-1)÷(s-1),s+j+(j-1)÷(s-1))for j=1:2(s-1)n)...)end)

This is a functional solution which computes for every index pair i,j what the symbol should be displayed.

Try it online!

Illustration

Start with a grid

f(i,j,u=mod(i,2s),v=mod(j,2s))=(" -|*")[1+(u==0)+2(v==0)]
for i=1:2(s-1)m println((f(i-1,j)for j=1:2(s-1)n)...)end

---------*---------*----
         |         |    
         |         |    
         |         |    
         |         |    
         |         |    
         |         |    
         |         |    
         |         |    
         |         |    
---------*---------*----
         |         |    
         |         |    
         |         |    
         |         |    
         |         |    

r > 0 means thicker lines

f(i,j,u=mod(i+r,2s),v=mod(j+r,2s))=(" -|*")[1+(u<=2r)+2(v<=2r)]
for i=1:2(s-1)m println((f(i,j)for j=1:2(s-1)n)...)end

**-----*****-----*****--
**-----*****-----*****--
||     |||||     |||||  
||     |||||     |||||  
||     |||||     |||||  
||     |||||     |||||  
||     |||||     |||||  
**-----*****-----*****--
**-----*****-----*****--
**-----*****-----*****--
**-----*****-----*****--
**-----*****-----*****--
||     |||||     |||||  
||     |||||     |||||  
||     |||||     |||||  
||     |||||     ||||| 

Handle the corners by checking which line on the original grid is closest

f(i,j,u=mod(i+r,2s),v=mod(j+r,2s))=(" -|")[abs(u-r)<abs(v-r)?1+(u<=2r):1+2(v<=2r)]
for i=1:2(s-1)m println((f(i,j)for j=1:2(s-1)n)...)end

|-------|||-------|||---
||-----|||||-----|||||--
||     |||||     |||||  
||     |||||     |||||  
||     |||||     |||||  
||     |||||     |||||  
||     |||||     |||||  
||-----|||||-----|||||--
|-------|||-------|||---
---------|---------|----
|-------|||-------|||---
||-----|||||-----|||||--
||     |||||     |||||  
||     |||||     |||||  
||     |||||     |||||  
||     |||||     |||||  

A fairy tells us to remove every s-1 line

f(i,j,u=mod(i+r,2s),v=mod(j+r,2s))=(" -|")[abs(u-r)<abs(v-r)?1+(u<=2r):1+2(v<=2r)]
for i=1:2(s-1)m println((f(i+(i-1)÷(s-1),s+j+(j-1)÷(s-1))for j=1:2(s-1)n)...)end

---||------||------||---
--||||----||||----||||--
  ||||    ||||    ||||  
  ||||    ||||    ||||  
  ||||    ||||    ||||  
  ||||    ||||    ||||  
--||||----||||----||||--
---||------||------||---
---||------||------||---
--||||----||||----||||--
  ||||    ||||    ||||  
  ||||    ||||    ||||  
  ||||    ||||    ||||  
  ||||    ||||    ||||  
--||||----||||----||||--
---||------||------||---

Traverse diagonally and done

f(i,j,u=mod(i-j+r,2s),v=mod(j+i+r,2s))=(" \\/")[abs(u-r)<abs(v-r)?1+(u<=2r):1+2(v<=2r)]
for i=1:2(s-1)m println((f(i+(i-1)÷(s-1),s+j+(j-1)÷(s-1))for j=1:2(s-1)n)...)end

 ///\\\  ///\\\  ///\\\ 
////\\\\////\\\\////\\\\
////\\\\////\\\\////\\\\
///  \\\///  \\\///  \\\
\\\  ///\\\  ///\\\  ///
\\\\////\\\\////\\\\////
\\\\////\\\\////\\\\////
 \\\///  \\\///  \\\/// 
 ///\\\  ///\\\  ///\\\ 
////\\\\////\\\\////\\\\
////\\\\////\\\\////\\\\
///  \\\///  \\\///  \\\
\\\  ///\\\  ///\\\  ///
\\\\////\\\\////\\\\////
\\\\////\\\\////\\\\////
 \\\///  \\\///  \\\/// 

mschauer

Posted 2017-10-31T16:35:05.297

Reputation: 1 348

3

JavaScript (ES6), 154 bytes

f=
(m,n,s,r)=>[...Array((s+=r)*n*2)].map((_,i)=>[...Array(s*m*2)].map((_,j)=>i/s&1^j/s&1?`\\ `[g(j%s)]:`/ `[g(s-1-j%s)],g=j=>i%s-j>r|j-i%s>r).join``).join`
`
<div oninput=o.textContent=f(+m.value,+n.value,+s.value,+r.value)>
m: <input type=number min=0 id=m><br>
n: <input type=number min=0 id=n><br>
s: <input type=number min=0 id=s><br>
r: <input type=number min=0 id=r></div>
<pre id=o>

Directly calculates the character at each cell of the output.

Neil

Posted 2017-10-31T16:35:05.297

Reputation: 95 035

2

CJam, 44

q~:R+,_ff{-zR>}{_W%:~\+"\ /"f=}%_W%Wf%+*f*N*

Try it online

Explanation:

q~           read and evaluate the input
:R+          save the last number in variable R, then add the last 2 numbers (s+r)
,_           make an array [0 1 … s+r-1] and duplicate it
ff{…}        make a matrix, calculating for each (x,y) pair from the 2 arrays:
  -z         abs(x-y)
  R>         compared with R (1 if greater, 0 if not)
{…}%         transform each row of the matrix:
  _W%        duplicate and reverse it
  :~         bitwise-NOT each element (0 → -1, 1 → -2)
  \+         prepend to the original row
  "\ /"f=    replace numbers with characters from this string (by index):
              0 → '\'; 1, -2 → ' '; -1 → '/'
              this generates the "/\" part
_W%          duplicate the matrix and reverse the rows
Wf%+         reverse each row, then append (by rows) to the original matrix
              this adds the "\/" part
*            repeat the matrix (by rows) n times
f*           repeat each row m times
N*           join the rows with newlines

aditsu quit because SE is EVIL

Posted 2017-10-31T16:35:05.297

Reputation: 22 326

2

C# (.NET Core), 167 bytes

(c,r,s,n)=>{int w=s+n,i=0,j;var g="";for(;i<r*2*w;i++,g+="\n")for(j=0;j<c*2*w;){int y=i%w,q=(j/w+i/w+1)%2,p=~-w*q+j++%w*(1-2*q);g+=p>y+n|p<y-n?' ':"\\/"[q];}return g;}

Try it online!

I'm surprised by the size I managed; I was initially expecting a longer solution. In saying this, I'm sure there are other tricks I've missed.

DeGolfed

(c,r,s,n)=>{
    int w=s+n, // rhombus quadrant width, and height
        i=0, // string row
        j; // string column

    var g="";

    // go through every character row and column
    for(; i < r*2*w; i++, g += "\n")
        for(j = 0; j < c*2*w;)
        {
            int y = i % w, // vertical position in the quadrant
                q = ( j / w + i / w + 1) % 2, // Get the rhombus quadrant as a 0 or 1
                p = ~-w * q + j++ % w * (1-2*q); // horizontal position in quadrant. the value is either ascending or descending depending on the quadrant

            // select which character to use at this [i,j] position
            g += p > y + n | p < y - n ? ' ' : "\\/"[q];
        }

    return g;
}

Ayb4btu

Posted 2017-10-31T16:35:05.297

Reputation: 541

1

Python 2, 201 189 bytes

def f(m,n,s,r):Z=range(s+r);R=[r-~min(i,s+~i+r,min(s-1,r))for i in Z];L=[m*(' '*(s+~i)+'/'*R[i]+'  '*(i-r)+'\\'*R[i]+' '*(s+~i))for i in Z];print'\n'.join((L+[l[s+r:]+l[:s+r]for l in L])*n)

Try it online!

Uses the fact that the bottom is the same as the top, but shifted:

Top:       /\/\/\
Bottom:     /\/\/\

Saved 22 bytes thanks to Jonathan Frech

TFeld

Posted 2017-10-31T16:35:05.297

Reputation: 19 246

s-i-1 can be s+~i, saving two bytes. r+1+min(... can be r-~min(..., saving another one. L=[(...)*m for can be L=[m*(...)for, saving one more byte. – Jonathan Frech – 2017-11-01T23:15:10.037

L+=[...];print'\n'.join(L*n) can be print'\n'.join((L+[...])*n) to save another byte, resulting in 196 bytes. – Jonathan Frech – 2017-11-01T23:18:37.737

195 bytes, if one also replaces s+r-i-1 with s+~i+r. – Jonathan Frech – 2017-11-01T23:20:52.243

190 bytes. – Jonathan Frech – 2017-11-01T23:22:18.210

Alternative 192 bytes version or 191 bytes version using exec and string formatting.

– Jonathan Frech – 2017-11-01T23:28:35.867

189 bytes by using an imperative function. – Jonathan Frech – 2017-11-01T23:35:54.687

@JonathanFrech Thanks a lot :) – TFeld – 2017-11-02T07:42:30.183

1

Perl 5, 159 + 3 (-anl) bytes

($m,$n,$s,$r)=@F;$s=$"x($s+$r-1);$_="$s/\\$s"x$m;$n*=2;{$t=$_;map$t=~s, ?(\S) ?,$1x$&=~y///c,ge,1..$r;print$t;redo if s, /,/ ,g&&s,\\ , \\,g||y,/\\,\\/,&&--$n}

Try It Online

Nahuel Fouilleul

Posted 2017-10-31T16:35:05.297

Reputation: 5 582