Author Topic: How would you draw L Pattern  (Read 1041 times)

0 Members and 1 Guest are viewing this topic.

Offline King123Topic starter

  • Contributor
  • Posts: 18
  • Country: in
How would you draw L Pattern
« on: August 13, 2022, 12:30:34 pm »
Hi,

I want to make it clear in advance that what I am asking is not homework. I have chosen a problem for myself that I want to solve. I don't need code I need your help to solve problem.

I just want to see how do you think to solve a problem. I think this would be the simplest letter in alphabet to print

I want to draw L pattern in c programming.

I am using nested for loop to create 10 rows and 10 columns

I do not understand what to do so that only the first column and the last row are printed.
 

Online Ian.M

  • Super Contributor
  • ***
  • Posts: 12855
Re: How would you draw L Pattern
« Reply #1 on: August 13, 2022, 12:50:06 pm »
So you want to generate 10x10 bitmap characters, and presumably already have a method of outputting bitmap data to a display device.

The usual way to do this is to store the pixel data for each character in a const 2D array, with the first index being the character code, and the second being the row (or column) of binary data, where each '1' bit indicates that pixel is on/foreground color and each '0' bit indicates off/background color.   Whether you organize the font data by rows or by columns depends on the word => pixel layout of your display device.   Your 10 bit data would be zero padded to form 16 bit words that can be stored as uint16_t.  Assuming you are using a cross-compiler for an embedded MCU/CPU that supports binary constants, or GCC, and your data is organized by rows, MSB on the left, you can directly enter your font data in the patterns it will be displayed in as binary constants (prefix 0b). 

e.g.:
Code: [Select]
uint16_t letter_L[10]={
      0b0100000000,
      0b0100000000,
      0b0100000000,
      0b0100000000,
      0b0100000000,
      0b0100000000,
      0b0100000000,
      0b0100000000,
      0b0111111111,
      0b0000000000
};
which assumes the first column and last row are normally left blank, for seperation from the previous character's bitmap and from the next line of text.

Note that I have shown a single dimension array for a single letter.  Unless memory is not a constraint, you wouldn't use raw ASCII for the character coding, as you'd probably want to eliminate the first 32 non-printing characters and may not need the full ASCII character set, so may need to write a mapping function to translate ASCII codes to your character coding.
« Last Edit: August 13, 2022, 03:44:17 pm by Ian.M »
 

Offline King123Topic starter

  • Contributor
  • Posts: 18
  • Country: in
Re: How would you draw L Pattern
« Reply #2 on: August 13, 2022, 01:44:18 pm »
So you want to generate 10x10 bitmap characters, and presumably already have a method of outputting bitmap data to a display device.
Sorry for misunderstanding maybe I didn't draft my question properly. Like we make pyramids in C programming from ⭐ I am trying to make L from star ⭐
 

Offline pcprogrammer

  • Super Contributor
  • ***
  • Posts: 3690
  • Country: nl
Re: How would you draw L Pattern
« Reply #3 on: August 13, 2022, 03:19:30 pm »
I don't really get what it is you want, but to draw a L shape in a 10x10 grid I would start with some sort of vectors defining what I want to draw. Where the vector has a start point and an end point.

x0,y0 - x0,y10 for the | of the L and x0,y10 - x10,y10 for the _ of the L.

And then write code to convert these vectors into the on bits in the 10x10 grid.

Another option is to use a vector with a start point, an angle and a length. Then use math to calculate the points that need to be set.

No nested for loop to calculate the points for a single vector, just a single loop to calculate points.

To draw all the vectors you need another loop to walk through the vectors.

Online Ian.M

  • Super Contributor
  • ***
  • Posts: 12855
Re: How would you draw L Pattern
« Reply #4 on: August 13, 2022, 03:52:30 pm »
So you want to generate 10x10 bitmap characters, and presumably already have a method of outputting bitmap data to a display device.
Sorry for misunderstanding maybe I didn't draft my question properly. Like we make pyramids in C programming from ⭐ I am trying to make L from star ⭐
Ah, I've got you - its job interview test coding pattern stupidity.
This certainly wont win you the job, but is almost certainly the simplest/shortest way to output a 10x10 L in * characters!
Code: [Select]
#include<stdio.h>
int main(){   
    printf("*\n*\n*\n*\n*\n*\n*\n*\n*\n**********\n");
}
 

Offline golden_labels

  • Super Contributor
  • ***
  • Posts: 1208
  • Country: pl
Re: How would you draw L Pattern
« Reply #5 on: August 13, 2022, 04:52:23 pm »
Iam.M failed the test: used a formatting function to output fixed text! :o

King123:
Can you show us, what are your attempts so far? And I do not want your non-working code: I am asking about a description of what is your thinking process in this case, precisely.
People imagine AI as T1000. What we got so far is glorified T9.
 

Offline King123Topic starter

  • Contributor
  • Posts: 18
  • Country: in
Re: How would you draw L Pattern
« Reply #6 on: August 13, 2022, 05:02:30 pm »

Ah, I've got you - its job interview test coding pattern stupidity.
This certainly wont win you the job, but is almost certainly the simplest/shortest way to output a 10x10 L in * characters!
Code: [Select]
#include<stdio.h>
int main(){   
    printf("*\n*\n*\n*\n*\n*\n*\n*\n*\n**********\n");
}
yes it is the easy way but it is not what i want.

This method is not suitable if I want output a 2000x2000 L in * characters!

Now how can we develop algorithm to get this output or what logic would be useful to implement it?

 

Offline IanB

  • Super Contributor
  • ***
  • Posts: 11859
  • Country: us
Re: How would you draw L Pattern
« Reply #7 on: August 13, 2022, 05:06:36 pm »
Hi,

I want to make it clear in advance that what I am asking is not homework. I have chosen a problem for myself that I want to solve. I don't need code I need your help to solve problem.

I just want to see how do you think to solve a problem. I think this would be the simplest letter in alphabet to print

I want to draw L pattern in c programming.

I am using nested for loop to create 10 rows and 10 columns

I do not understand what to do so that only the first column and the last row are printed.


You have answered your own question in the red text. Why don't you just write a program that does what the red text says?

In other words:
Code: [Select]
for rows from 1 to 10:
    for columns from 1 to 10:
        if first column or last row print '*' else print ' '

Have you tried this, and where are you getting stuck? Please post your code so we can see what you have tried so far.
 

Online Ian.M

  • Super Contributor
  • ***
  • Posts: 12855
Re: How would you draw L Pattern
« Reply #8 on: August 13, 2022, 05:09:48 pm »
Ian.M failed the test: used a formatting function to output fixed text! :o
You expect the O.P. and the interviewer to know about puts()?  :popcorn:

Here's a typical example of the level of coding you are up against! https://quescol.com/interview-preparation/pyramid-pattern-programs-in-c


This method is not suitable if I want output a 2000x2000 L in * characters!

Now how can we develop algorithm to get this output or what logic would be useful to implement it?



Loop 2N-1 times{
putchar('*');
If loop_count<N then putchar('\n');
}End Loop
putchar('\n');
 

Online Nominal Animal

  • Super Contributor
  • ***
  • Posts: 6239
  • Country: fi
    • My home page and email address
Re: How would you draw L Pattern
« Reply #9 on: August 14, 2022, 09:57:04 pm »
I often use Netpbm image formats for my code and math experiments, especially the binary P6 format with 24-bit RGB color, because it is trivial to output from a program and easy to display, or convert to e.g. PNG or JPEG.

Here, it is the core idea that matters: using an array of some sort, as a canvas to draw to, and then output the contents of that canvas in a suitable format.

If you do not have color, only presence/absence –– foreground/background, asterisk or space ––, then using binary, one bit per pixel, is the most efficient way.  This is what Ian.M described in reply #1.

If you use color, or more generally have more than two states per pixel, then each pixel needs a larger range of values, so it is common to use an array of chars, or perhaps one of the uintN_t exact-size integer types as provided by <stdint.h> or <inttypes.h>.

For example, you could use
Code: [Select]
const unsigned char  canvas[5][4] = {
    { 1, 3, 0, 0 },
    { 4, 6, 0, 0 },
    { 4, 6, 0, 0 },
    { 4, 7, 2, 3 },
    { 7, 8, 8, 9 },
};
If one uses char as the array element type, then one can specify each row as a string.  However, then the elements of the array are the numbers corresponding to those characters, most often their ASCII code.  (Unicode, ISO Western European, and Windows Western European code page character sets are all compatible with ASCII codes – they just extend the ASCII set, basically –, so that's why we still use the ASCII code table even though we usually use much larger character sets nowadays.)
Also, because each string is terminated by a NUL char (0 or '\0'), one should reserve space for that in the horizontal/last dimension.

Now, those digits are actually not random at all.  I chose them using the following logic:
    1 2 3     ┌ ─ ┐
    4 5 6  =  │ ╳ │  with 0 as blank
    7 8 9     └ ─ ┘
so that logically, the canvas above describes a 4-column, 5-row figure,
    ┌┐ 
    ││ 
    ││ 
    │└─┐
    └──┘
(For this figure, I used the Unicode Box Drawing block, which is supported by browsers, but may need extra support from your C code to output from a program, especially if you are using Windows, or use a sensible operating system but not an UTF-8 -based locale.)

The reason for doing that is that if you wanted to output the shape in a very large form, you could then define a set of arrays to describe each pixel in your output.  If you make those say 8×8, you could then emit the figure as 40 rows and 32 columns.  If those define binary pixels (foreground/background, visible/blank), then you can apply an another level of scaling, by outputting each pixel as a rectangular block of pixels all in that same state.

This last step in scaling is probably what OP is actually looking for right now.

The idea is that when we scale each pixel to R rows and C columns, and we output in row-major order (the same order this text is written in, as rows of text from left to right, rows from top to bottom), we repeat each row R times.  Within each row, we duplicate each pixel to C.

For example, if we use the array
Code: [Select]
const unsigned char  letter_L[5] = {
     1, /*  1 + 0 + 0 + 0 */
     1, /*  1 + 0 + 0 + 0 */
     1, /*  1 + 0 + 0 + 0 */
     1, /*  1 + 0 + 0 + 0 */
    15, /*  1 + 2 + 4 + 8 */
};
to encode a 4-column, 5-row canvas in the four least significant bits of unsigned chars (they are guaranteed to have at least 8 bits in C), we can emit it using for example
Code: [Select]
void output_canvas(const unsigned char *canvas, int rowscale, int colscale, int bit1, int bit0, FILE *out)
{
    for (int row = 0; row < 5; row++) {
        for (int rowrepeat = 0; rowrepeat < rowscale; rowrepeat++) {
            for (int col = 0; col < 4; col++) {
                const int bit = (canvas[row] >> col) & 1;
                for (int colrepeat = 0; colrepeat < colscale; colrepeat++) {
                    if (bit) {
                        fputc(bit1, out);
                    } else {
                        fputc(bit0, out);
                    }
                }
            }
            fputc('\n', out);
        }
    }
}
so that if you called output_canvas(letter_L, 7, 6, '*', ' ', stdout); you'd get a 7×5=35-row, 6×4=24-column letter L on standard output, consisting of asterisks (*) and spaces ( ).

Consider the four nested loops above.  If we added a lookup, so that clear bits are described by one canvas, and set bits by another, both rowscale rows and colscale columns, then bit specifies the lookup canvas, rowrepeat the row within the lookup canvas, and colrepeat the column within the lookup canvas.

If we used a structure to describe a canvas, say
Code: [Select]
#include <stdlib.h>
#include <limits.h>

typedef  unsigned long  cell;
#define  CELL_BITS  (sizeof (unsigned long) * CHAR_BIT)

typedef struct {
    int  rows;
    int  columns;
    size_t  stride;  /* Number of data cells per row */
    cell *data;
} bitcanvas;

void bitcanvas_set(bitcanvas *canvas, int row, int column)
{
    if (canvas && row >= 0 && row < canvas->rows && column >= 0 && column < canvas->columns)
        canvas->data[(size_t)row * canvas->stride + (size_t)column / CELL_BITS] |= 1 << (column % CELL_BITS);
}

int bitcanvas_get(bitcanvas *canvas, int row, int column)
{
    if (canvas && row >= 0 && row < canvas->rows && column >= 0 && column < canvas->columns)
        return (canvas->data[(size_t)row * canvas->stride + (size_t)column / CELL_BITS] >> (column % CELL_BITS)) & 1;
    else
        return 0;
}

void bitcanvas_free(bitcanvas *canvas)
{
    if (canvas) {
        free(canvas->data);
        canvas->rows = 0;
        canvas->columns = 0;
        canvas->stride = 0;
        canvas->data = NULL;
    }
}

int  bitcanvas_init(bitcanvas *canvas, int rows, int columns)
{
    size_t  stride;

    /* No canvas? */
    if (!canvas)
        return -1;

    /* We're diligent, and clear the structure to known invalid values first. */
    canvas->rows = 0;
    canvas->columns = 0;
    canvas->stride = 0;
    canvas->data = NULL;

    /* Invalid size? */
    if (rows < 1 || columns < 1)
        return -1;

    /* Number of cells on each row: columns / BITS_PER_CELL, rounded up. */
    stride = ((size_t)columns + BITS_PER_CELL - 1) / BITS_PER_CELL;

    /* Allocate canvas data dynamically. */
    canvas->data = calloc(stride, (size_t)rows);
    if (!canvas->data)
        return -1;

    canvas->rows = rows;
    canvas->columns = columns;
    canvas->stride = stride;

    return 0;
}
then the scaled output –– drawing one canvas using two other canvases (of the same size) for each pixel –– would be rather straightforward:
Code: [Select]
void output_mapped_bitcanvas(bitcanvas *canvas, bitcanvas *bit1, bitcanvas *bit0, int pixel1, int pixel0, FILE *out)
{
    /* Safety checks first. */
    if (!canvas || canvas->rows < 1 || canvas->columns < 1 ||
        !bit1 || bit1->rows < 1 || bit1->columns < 1 ||
        !bit0 || bit0->rows != bit1->rows || bit0->columns != bit1->columns ||
        !out)
        return;

    for (int row = 0; row < canvas->rows; row++) {
        for (int subrow = 0; subrow = bit1->rows; subrow++) {
            for (int column = 0; column < canvas->columns; column++) {
                bitcanvas *bit = bitcanvas_get(canvas, row, column) ? bit1 : bit0;
                for (int subcolumn = 0; subcolumn = bit1->columns; subcolumn++) {
                    fputc(bitcanvas_get(bit, subrow, subcolumn) ? pixel1 : pixel0, out);
                }
            }
            fputc('\n', out);
        }
    }
}
where (expression) ? (if-true) : (if-false) is the ternary conditional expression in C.  If the expression is true or nonzero, then the statement evaluates to (i]if-true[/i]), otherwise it evaluates to (if-false).  Consider it a condensed form of an if statement, except inside an expression so that it always evaluates to one of the results.

The point of this latter part is to show OP exactly why structures and splitting operations into separate functions is so powerful.  With a very similar loop that can scale a bitmap using "dumb" repetition, we can scale a bitmap using two other bitmaps to represent each state!

And yes, we could add two or four other bitmaps, to describe each bit in the sub-bitmaps, with not too much effort, but it so quickly becomes so large that standard output no longer suffices.  Which brings me a full circle to the beginning of this post, to Netpbm image formats.  It would be very straightforward to add a function that saves a bitcanvas as a PBM file.  I could then also add a function that creates a new bitmap by doing what output_mapped_bitcanvas() does, describing each pixel/bit in one canvas by one of two other canvases.  And even the three-layer one, for those really big images.  Finally, add a blit function that copies a canvas to a specific position in another canvas, and you can start building some really complex bitmap images.  (It also leads to a fun little rabbit hole called rasterization, which can easily take years to explore.  I'm personally still deep in there somewhere!)

And all this not really that far from the initial asterisk experiments...  A lot to learn, for sure, but fun as heck, too.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf