10
$\begingroup$

Why do we practice printing patterns while coding? Patterns like:

1
1 2
1 2 3
1 2
1

1
2 3
4 5 6
7 8 9 10
11 12 13 14 15, etc.

Are these kinds of pattern questions just for fun and to get better at using loops, or are there any interesting applications of these types of pattern questions? Or any interesting math behind them?

$\endgroup$
6
  • 2
    $\begingroup$ Fast feedback loops! $\endgroup$
    – WBT
    Mar 30 at 19:09
  • 3
    $\begingroup$ Depending on the language and the pattern, it may also be to get better at using recursion properly. Assuming I was told to do a parameterized implementation of either of your examples in a language like Elixir (or pretty much any other language with proper TCO) I would actually jump first to a recursive implementation even if looping were possible in the language. $\endgroup$ Mar 30 at 23:08
  • 1
    $\begingroup$ Turning a mathematical expression or idea into an algorithm is not always a 1:1 translation. It seems to be a "hard thing", generally, for programmers to adapt mathematics into code. This type of practice helps those skills, and they are important in many fields of applied science and engineering. $\endgroup$
    – J...
    Apr 1 at 16:01
  • $\begingroup$ @AustinHemmelgarn These sort of patterns would likely be poor applications of recursion for imperative languages, though, which is the common case. CS educators forcing students to use recursion for O(n^2) loop problems like this causes a lot of hapless students to wind up in the recursion tag on Stack Overflow. $\endgroup$
    – ggorlen
    Apr 5 at 15:41
  • $\begingroup$ @ggorlen Agreed, which is why I prefaced my comment with ‘depending on the language’. I would never consider recursion for something like this in a language like C or Python, but would absolutely prefer it to any other looping-equivalent construct in something like Elixir or Erlang. $\endgroup$ Apr 5 at 16:44

8 Answers 8

31
$\begingroup$

Why do we practice printing patterns while coding?

Because bugs love to hide in loops.

Talk students into using loops to print these patterns and they will create bugs. Tracking down and squishing bugs in the confusing code this exercise produces is a skill that will last as long as their coding career.

Fail to talk them into using loops and you'll find they very wisely write a bug free print statement for each line of your output. Which solves the problem without learning the lesson. Have a good explanation why this isn't preferred. Understand that you likely wont find a good technical explanation. Sometimes pros do the same thing. It's called loop unrolling.

Don't claim loops are more flexible, efficient, or readable. They aren't. Loops just follow patterns. Sometimes they are a good way to express the pattern. Capturing a pattern in a loop gives you expressive power. It lets you create, manipulate, and display things that follow the pattern.

This is an exercise in pattern recognition, loop construction, and debugging. Pull this off and I consider you a real coder.

are there any interesting applications of these types of pattern questions?

Absolutely. They range from silly toys most often used in job interviews: FizzBuzz

To beefy algorithms used to keep growing networks working: Dijkstra's_algorithm

While they have wildly different applications, both really just manipulate numbers to follow a pattern.

$\endgroup$
26
  • 10
    $\begingroup$ "Don't claim loops are more flexible […]. They aren't." - well hardcoding a pattern works well for a single pattern. Now make the exercise to print the pattern in an arbitrary size, or to print the first N lines of the infinite pattern… I can't see how you'd do that without the flexibility of a loop (or recursion). $\endgroup$
    – Bergi
    Mar 30 at 21:11
  • 3
    $\begingroup$ @Bergi That isn't more flexibility. That's parameterizing. A student with access to copy and paste and the code has the same flexibility and easier to debug code. The trick is getting them to see why changing N is better than copy and paste. The answer is sometimes you don't know N until this code is running on some server at 3am. I could have my boss wake me up with phone call about it but I'd rather sleep through the night. $\endgroup$ Mar 30 at 21:35
  • 9
    $\begingroup$ By this argument, no code is more flexible than a collection of special-cases. I'd argue the flexibility provided by loops is the flexibility provided to another individual, who may not have the same knowledge as you do. In many cases, this is a user who provides input, in the form of a file or otherwise. In the case of std::sort, it is in the form of a developer who may not have the understanding of sorting algorithms, or may not wish to exercise said understanding. $\endgroup$
    – Cort Ammon
    Mar 31 at 2:30
  • 3
    $\begingroup$ @haxor789: The only time I ever need loops is to work around deficiencies in the programming language and/or the library. In most languages I work in, if you're using a loop you're doing it wrong. Some of them don't even have loops. I, personally, find recursion patterns like anamorphisms, catamorphisms, or hylomorphisms much easier to understand and most importantly much harder to get wrong (can't have an off-by-one indexing error if there's no index). If all else fails, there's always tail-recursion. $\endgroup$ Mar 31 at 13:14
  • 2
    $\begingroup$ @candied_orange JörgWMittag The point is about the coding patterns that let you avoid repetition, perform an operation stepwise, let's you manipulate datastructures manually if necessary instead of relying on knowledge of the commands of a particular language and stuff like that. Whether you use go to, for/while/do-while/for each or recursions doesn't really matter. Does it even conceptually matter whether the language optimizes tail-recursions? $\endgroup$
    – haxor789
    Mar 31 at 13:31
9
$\begingroup$

Are these kinds of pattern questions just for fun and to get better at using loops [...] ?

Absolutely yes. Practical applications of such patterns nearly don't exist. It's good training for control constructs like loops, and you can immediately see whether you got it right.

$\endgroup$
3
  • 5
    $\begingroup$ Practical applications of algorithms that can generate such patterns do exist and are very common. They include: generating node traversal sequences in pathfinding or graph crawling algorithms, generating brute force password sequences, similar to the brute force, generating permutations or combinations to solve word problems (eg, Wordle solver, Scrabble solver or the first part of decoding an encrypted message if you have a rough idea of some of the content of the message) etc.. $\endgroup$
    – slebetman
    Mar 31 at 3:02
  • 4
    $\begingroup$ I almost applied for a job once at a company building sewing machines with lots of very clever software - yes, I might have written lots of code to create patterns. Seriously :-) $\endgroup$
    – gnasher729
    Mar 31 at 10:01
  • $\begingroup$ The tree command is another nice example of loops, recursion and printing. It is great visual tool for understanding the structure of directories and their contents. $\endgroup$ Apr 2 at 15:35
6
$\begingroup$

I was skeptical about this as well. Those pictures feel like a cheesy attempt to make programming cool, from an era when that meant ASCII graphics; or the sort of cutsie junk we need to keep the attention of non-majors. But I've come around to realize they're nice teaching examples of nested loops, at a few levels.

The way nested loops work isn't obvious. Showing how for i=1 to 8; { for j=1 to 5; print "*" } actually prints 40 stars (and not 13) is helpful. Adding the newline for that 8x5 box is a nice way to visualize how the loops run.

Making a silly right triangle with for i=0 to 7; for j=0 to i introduces the idea of using the outer loop variable to influence the inner loop. That's an idea we'll need later for O($n^2$) selection and insertion sorts. Different patterns allow us to use i in different places j=i to WIDTH (right-triangle on right edge) or even both sides -- j=i to WIDTH-i (pyramid).

More complex things, pyramids or X's or a hollow square, are nice practice with 0-based index math -- how i runs from 0 to HEIGHT-1 and how to plug that into j<HEIGHT-i to reason about the length of the 1st and last row. Off-by-one errors are very easy to spot in these pictures.

All of this is nice for ComSci majors who'll need to be good with this stuff for their algorithms classes. But even for an aspiring web developer in a 2-year program, these are a quick warm-up for creating a table, before adding all of the mark-up.

Coding note: the examples change a little for console vs. graphical system, but not the essence. If printed on a simple console, sometimes the inner loop must run 0 to WIDTH, with the interesting part inside. Ex: if(i<WIDTH-j) ch=" "; else ch="*";. Whereas with a graphical system, the inner loop can do the work: j=WIDTH-i to WIDTH; colorBox(i,j). Or on a console we can fake that by "printing" into a 2D array which a function displays later.

$\endgroup$
6
  • $\begingroup$ It's not really "cool designs" from way back. It's to get non-programmers their first experience with looping. - I taught CS. $\endgroup$ Mar 31 at 19:26
  • 1
    $\begingroup$ @RickHenderson They are from way back -- books of BASIC programs from the 1980's had them. But thanks for the "for non-majors" idea. That aligns with my 1st para that it's easy to assume these are cutsie junk, useless for "real" CS majors. $\endgroup$ Mar 31 at 20:47
  • 1
    $\begingroup$ Off-by-one errors are very easy to spot in these pictures - I think that's really the key point. Not only is the desired output tied closely to each step of execution, like a debug-print and unlike for example a sorting algorithm, the actual shape will be visually wrong for some kinds of bugs. For students who might not have learned how to use a debugger yet, this code is still very debugable except in the very lowest-level languages (like assembly) where even printing numbers as ASCII digit-strings takes some work and there are calling-conventions you can get wrong. $\endgroup$ Apr 1 at 20:20
  • $\begingroup$ Loops where you aren't printing something every iteration as part of the desired output don't have this feature, and debugging them might require single-stepping in a debugger (or adding debug-prints), and could still be trickier to follow. $\endgroup$ Apr 1 at 20:23
  • $\begingroup$ @OwenReynolds The idea holds that it's still about learning loops and not pretty pictures. There are CS majors who start first year having never coded before. Trust me. $\endgroup$ Apr 1 at 22:45
2
$\begingroup$

I let my students generate Pascal's triangle as a data structure. That's an exercise in loops.

And then they have print the triangle modulo some number n: print a star when the entry modulo n is zero, a space otherwise. Instant fractals!

So there you essentially need to generate screen output.

$\endgroup$
0
2
$\begingroup$

I think examples like these

1
1 2
1 2 3
1 2
1

1 
2 3
4 5 6
7 8 9 10
11 12 13 14 15 etc.

serve different purposes, e.g.:

  • Recognize or derive a construction (input)pattern from the optical (output) pattern
  • Numbers are probably the most primitive example of unique absolutely order-able items
  • It's probably rather easy to verify whether the solution is correct (comparing outputs)
  • the human brain is rather good detecting and recognizing patterns
  • Adding details like fancy strings instead of simple digits will just hide the essential structure

BTW: The first example is a stack where elements are popped from the right, while the second example is a stack where elements are popped at the left ;-)

$\endgroup$
3
  • 3
    $\begingroup$ You are right about the first one, that is a classic stack, but you missed the second one, it's a simple nested loop. You wouldn't use a stack for this and if you use a queue then you've overcomplicated things, there are better patterns to compare stacks to queues. $\endgroup$ Mar 31 at 13:47
  • 3
    $\begingroup$ +1 unlike in many other exercises, the output closely matches the flow of the program, making it easy to visualize whats happening in the code. It looks just like the output of a "printf-debugged" program. $\endgroup$ Mar 31 at 14:05
  • $\begingroup$ @PhilipRoman: I think Owen Reynold's answer comes closer to saying exactly that, but yeah, I'm not sure anyone's posted an answer where that's the main point. Except the question's not asking why these are good teaching exercises, so maybe not. $\endgroup$ Apr 1 at 20:27
1
$\begingroup$

Patterns are everywhere in programming, and pattern recognition is the skill that is often so noticeably absent in fresh grads. They would often prefer to copy and paste code ad infinitum rather than recognize a pattern and avoid repetition through better design, inheritance, modularity, decorators, etc. Good question.

$\endgroup$
0
1
$\begingroup$

Most people understand the basis of numerical sequences and can see how one set of digits changes with each iteration.

This makes numerical sequences a very good fit for teaching people iterations and iterations are usually done in a loop.

The two examples you provide show two different types of loops. One appears to be sequential numbers, increasing by one digit for each line of the output, and the other repeats the same numbers, increases and then decreases the number of digits in the output.

The display of those simple numerical digits are a lot easier to understand than my description.

$\endgroup$
0
1
$\begingroup$

Are these kinds of pattern questions just for fun and to get better at using loops, or are there any interesting applications of these types of pattern questions? Or any interesting math behind them?

All of the above.

Fun is important. If learners aren't having fun, they're likely to quit. As an educator working with young children to adults from all walks of life, I've seen a lot of folks lose interest in programming, often because (I suspect) they didn't see the magic and power in it. Sure, for some learners, jumping into business applications might feel more purposeful than playing with patterns, so there is audience-specificity here.

There's something magical about loops and iterative processes in general. Being able to write a few lines of code and generate a pattern involves making the leap from 1 to 2 to 3 to an arbitrary n. Generalizing code and figuring out which parts are dynamic (i.e. parameters and variables) is a critical skill in programming. These loops provide visual feedback for this process and allow students to iterate on naive, hardcoded attempts until they've generalized the logic.

If you think of the characters on the screen as pixels, these nested loop exercises translate very well into computer graphics. I have a post on how you can animate these patterns. This is a useful teaching approach for languages other than Scratch and JavaScript that don't have a particularly easy way to make images and animations other than ASCII.

ASCII text applications like this connect students to computer history while increasing their comfort working in the always-relevant terminal ecosystem. ASCII art, Text adventures, creative coding, 10 PRINT, Figlet banners and other console-based applications are just as fun and useful today as they've ever been. npm is chock full of packages for animations, spinners, banners and colors to create user-friendly command line tools for programmers.

From a purely technical perspective, these exercises provide great opportunities for nesting conditions in loops, counting forwards and backwards, incrementing by something other than 1, understanding when for vs while is appropriate, getting comfortable with string manipulation and building up to arrays and functions. Given the fun factor and possibilities available, I don't think building an introductory course around ASCII patterns is a particulary absurd idea.

In regards to math, there can be as much or as little of it as you want in making these patterns. Consider patterns in triangular numbers, Pascal's Triangle and cellular automata, for starters. For the right audience, integrating trigonometric functions like sine and cosine functions can provide a great extension of possibilities. Fractals and L-Systems can be fun to play with, given the right resolution and reasonably experienced coders.

Finally, as an educator, puzzles like these offer a great source of assignments that are relatively difficult to find direct solutions for on the internet, potentially helping combat plagiarism. It's easy to communicate the deliverables by showing a few example runs and explaining that it should work on any n. These problems are language-agnostic.

Code Golf SE has over 1000 posts in the ascii-art tag ripe for exploration. Codewars has a good deal of ASCII shape printing problems with test cases (disclosure: I consult for the company that owns Codewars).

$\endgroup$
0

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.