How would you draw L Pattern  - Page 1
Forum section: electronics / general

author: King123
author_rank: Contributor
timestamp: August 13, 2022, 12:30:34 pm
content: 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 printI want to draw L pattern in c programming.I am using nested for loop to create 10 rows and 10 columnsI do not understand what to do so that only the first column and the last row are printed.

author: Ian.M
author_rank: Super Contributor
timestamp: August 13, 2022, 12:50:06 pm
content: 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 asbinary constants(prefix 0b).e.g.:Code:uint16_t letter_L={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.

author: King123
author_rank: Contributor
timestamp: August 13, 2022, 01:44:18 pm
content: Quote from: Ian.M on August 13, 2022, 12:50:06 pmSorry 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 ⭐

author: pcprogrammer
author_rank: Super Contributor
timestamp: August 13, 2022, 03:19:30 pm
content: 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.

author: Ian.M
author_rank: Super Contributor
timestamp: August 13, 2022, 03:52:30 pm
content: Quote from: King123 on August 13, 2022, 01:44:18 pmAh, 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:#include<stdio.h>int main(){printf("*\n*\n*\n*\n*\n*\n*\n*\n*\n**********\n");}

author: golden_labels
author_rank: Super Contributor
timestamp: August 13, 2022, 04:52:23 pm
content: Iam.M failed the test: used a formatting function to output fixed text!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.

author: King123
author_rank: Contributor
timestamp: August 13, 2022, 05:02:30 pm
content: Quote from: Ian.M on August 13, 2022, 03:52:30 pmyes 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?

author: IanB
author_rank: Super Contributor
timestamp: August 13, 2022, 05:06:36 pm
content: Quote from: King123 on August 13, 2022, 12:30:34 pmYou 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: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.

author: Ian.M
author_rank: Super Contributor
timestamp: August 13, 2022, 05:09:48 pm
content: Quote from: golden_labels on August 13, 2022, 04:52:23 pmYou expect the O.P. and the interviewer to know about puts()?Here's a typical example of the level of coding you are up against!https://quescol.com/interview-preparation/pyramid-pattern-programs-in-cQuote from: King123 on August 13, 2022, 05:02:30 pmLoop 2N-1 times{putchar('*');If loop_count<N thenputchar('\n');}End Loopputchar('\n');

author: Nominal Animal
author_rank: Super Contributor
timestamp: August 14, 2022, 09:57:04 pm
content: I often useNetpbmimage 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 acanvasto 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 perpixel, 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 ofchars, or perhaps one of theuintN_texact-size integer types as provided by<stdint.h>or<inttypes.h>.For example, you could useCode:const unsigned char canvas = {{ 1, 3, 0, 0 },{ 4, 6, 0, 0 },{ 4, 6, 0, 0 },{ 4, 7, 2, 3 },{ 7, 8, 8, 9 },};If one usescharas 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 theirASCIIcode. (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 blank7 8 9 └ ─ ┘so that logically, the canvas above describes a 4-column, 5-row figure,┌┐│││││└─┐└──┘(For this figure, I used the UnicodeBox Drawingblock, 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 toRrows andCcolumns, and we output inrow-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 rowRtimes. Within each row, we duplicate each pixel toC.For example, if we use the arrayCode:const unsigned char letter_L = {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 exampleCode: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 >> 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 calledoutput_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, bothrowscalerows andcolscalecolumns, thenbitspecifies the lookup canvas,rowrepeatthe row within the lookup canvas, andcolrepeatthe column within the lookup canvas.If we used a structure to describe a canvas, sayCode:#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;elsereturn 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: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), otherwise it evaluates to(if-false). Consider it a condensed form of anifstatement, 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 abitcanvasas a PBM file. I could then also add a function that creates a new bitmap by doing whatoutput_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 calledrasterization, which can easily takeyearsto explore. I'm personally still deep in there somewhere!)And all this not reallythatfar from the initial asterisk experiments... A lot to learn, for sure, but fun as heck, too.