5.4. Lab: for Loops#

  • Note that the course policy is that you should not use generative AI without authorization. If you are suspected to have used generative AI and not able to explain/reproduce your work when requested, all your related assignments throughout the semester will be regraded as 0.

  1. Create a dotnet console app project (Creating a C# Project), if you have not, in your USERNAME/workspace/introcscs directory; call it Ch05ForLoop.

  2. Prepare your code in VS Code.

  3. Use the file Program.cs to code.

  4. The namespace of this project is IntroCSCS.

  5. The class name of this project is Ch05ForLoop.

  6. When executing code, you will only use the Main() method in class Ch05ForLoop.

  7. You will prepare methods in the same class to be called from the Main() method.

  8. Use a Word document to prepare your assignment.

  9. Number the questions and annotate your answers (using // in code when appropriate) to show your understanding.

  10. For coding questions, screenshot and paste 1) your code in VS Code and 2) the results of the code’s execution (command prompt and username are part of the execution).

Goals for this lab:

  • Practice with loops. You are encouraged to use a for loop where appropriate.

  • Use nested loops where appropriate.

5.4.1. For Loop Lab#

This part of the lab comes from loop_lab_stub/loop_lab.cs. You may refer to the code while answering the questions here.

  1. From the terminal, go to your Ch05ForLoop project folder.

  2. code . + Enter from within the Ch05ForLoop directory.

  3. Start working on the methods.

Your task is to Fill in method bodies for each part below:

  1. Complete method PrintReps to be called from Main() like:

    /// Print n copies of s, end to end.
    /// For example PrintReps("Ok", 9) prints: OkOkOkOkOkOkOkOkOk
    static void PrintReps(string s, int n)
    

    Hint: How would you do something like the example PrintReps("Ok", 9) or with a higher count by hand? Probably count under your breath as you write:

     1 2 3 4 5 6 7 8 9
    OkOkOkOkOkOkOkOkOk
    

    This is a counting loop. Use a C-style for loop.

  2. Complete method StringOfReps

    /// Return a string containing n copies of s, end to end.
    /// For example StringOfReps("Ok", 9) returns: "OkOkOkOkOkOkOkOkOk"
    static string StringOfReps(string s, int n)
    

    Note the distinction from the previous part: Here the method prints nothing. Its work is returned as a single string. You have call the method like:

    Console.WriteLine(StringOfReps("Ok", 9));
    
  3. Complete method Factorial: (A factorial, in mathematics, is the product of all positive integers less than or equal to a given positive integer and denoted by that integer and an exclamation point.)

    /// Return n! (n factorial: 1*2*3 *...* n if n >=1;
    /// 0! is 1.).  For example Factorial(4) returns 1*2*3*4 = 24.
    static int Factorial(int n)
    

    It is useful to think of the sequence of steps to calculate a concrete example of a factorial, say 6!:

    Start with 1
    2 * 1 = 2
    3 * 2 = 6
    4 * 6 = 24
    5 * 24 = 120
    6 * 120 = 720
    

    ALSO find the largest value of n for which the method works. (You might want to add a bit of code further testing Factorial, to make this easier.) Caution: although a negative result from the product of two positive numbers is clearly wrong, only half of the allowed values are negative, so the first wrong answer could equally well be positive. Explain how you find the largest value of ``n`` that works in this method.

5.4.2. Head or Tails#

Write a method Flip(), that will just randomly print Heads or Tails once. Accomplish this by choosing 0 or 1 arbitrarily with a random number generator. More details follow.

Use a Random object, and make the Random object a local variable inside the Flip method.

It is generally a good idea to only create a single ``Random`` object that stays in scope for the whole program so it can be used by various programs. One way to do that is to make it static. For our purpose here, just place the random object declaration in your Flip() method:

Random r = new Random();

Note again that in the future you would place the object inside your class but outside of any method, so you can use ``r`` in any method in your class.

For int variables low and higher, with low < higher:

int n = r.Next(low, higher);

returns a (pseudo) random int, satisfying low <= n < higher. If you select low and higher as 0 and 2, so there are only two possible values for n, then you can choose to print Heads or Tails with an if-else statement based on the result.

In your Flip method, create a for loop so you generate a random sequence of 10 heads and/or tails. Print out the heads/tails like:

Tails Tails Tails Tails Heads Tails Heads Tails Tails Tails

Place return "" in your else block to avoid a “not all paths return value” warning if you use an else if statement (or simply put the return line at the end of the code block).

We have discovered some problems with the Next() implementation that sometimes results in random values not being generated. This is likely a bug that will be fixed. If you experience any problems with Next(), the following is for you!

5.4.3. Group Flips#

Write a method GroupFlips() using the Flip() method from the last question to:

/// Print out the results from the total number of random flips of a coin.
/// Group them groupSize per line, each followed by a space.
/// The last line may contain fewer than groupSize flips
/// if total is not a multiple of groupSize.  The last line
/// should be followed by exactly one newline in all cases.
/// For example, GroupFlips(10, 4) *could* produce:
///   Heads Heads Tails Heads
///   Heads Tails Heads Tails
///   Tails Tails
static void GroupFlips(int total, int groupSize)

Complete this method definition and test with a variety of calls to GroupFlips in Main. The output from the previous exercise would be produced by the call:

GroupFlips(10, 1);

5.4.4. Reverse String foreach#

It used a for loop to go through the characters in reverse order. Write a version with the only loop heading:

foreach(char ch in s) {

and no reference to indices in s.

5.4.5. Only Letters#

Write a program that defines and tests a method with description and heading:

/// Return s with all non-letters removed.
/// For example OnlyLetters("Hello, World!") returns "HelloWorld".
static string OnlyLetters(string s)

Assume the English alphabet.

5.4.6. Palindrome Exercise#

Write a program palindrome.cs that defines and tests a method with description and heading:

/// Return true when s is a palindrome.
/// For example IsPalindrome("A Toyota!") returns true.
static bool IsPalindrome(string s)

A palindrome is a string that contains the same sequence of letters, ignoring capitalization, forward and backward. Non-letters are ignored. Examples are “Madam, I’m Adam.” and “Able was I ’ere I saw Elba.”

IsPalindrome can be written very concisely by copying and using methods from previous exercises.

Predict what these code fragments print. Then check yourself in csharp:

for (int i = 3; i > 0; i--) {
    for (int j = i; j < 4; j++) {
        Console.Write(j);
    }
    Console.WriteLine();
}

string s = "abcdef";
for (int i = 1; i < s.Length; i += 2) {
    for (int k = 0; k < i; k++) {
        Console.Write(s[i]);
    }
}

5.4.7. Power Table#

  1. Write a method that completes and tests with this heading. Be sure your program tests with several values for each parameter:

    /// Print a table of powers of positive integers.
    /// Assume 1 <= nMax <= 12, 1 <= powerMax <= 7.
    /// Example: output of PowerTable(3, 4)
    ///       n^1       n^2      n^3      n^4
    ///         1         1        1        1
    ///         2         4        8       16
    ///         3         9       27       81
    ///
    public static void PowerTable(int nMax, int powerMax)
    

    Make sure the table always ends up with right-justified columns.

  2. Make the table have columns all the same width, but make the width be as small as possible for the parameters provided, leaving a minimal one space (but not less!) between columns somewhere in the table. Consider heading widths, too.

5.4.8. Reverse String Practice#

The following reverse-string examples were moved from worked examples as lab-style practice.

5.4.9. Reversed String Print#

Create a method, call it ReverseStringPrint, that, when called with a string, will print the string reversed.

We know we could use a for loop to print the characters in a string reversely. Let us consider the following tools we have:

  • A string is an array of combined characters with indices.

  • An array is 0-based. The first character of a string str can be accessed as str[0]

  • To reverse a string, we need to start from the last indexed character.

  • The last index number of string str is related to the length of the string: str.Length.

  • To process the whole string, we can use the decrement assignment operator (--) to start the printing from the end of the string.

I managed to come up with some variation of code as below but am running into some errors:

string s = "drab";
  for (int i = s.Length; i >= 0; i++)
  {
    Console.Write(s[i]);
  }

One of the errors I see is the famous Index-Out-Of-Range error:

┌──────────IndexOutOfRangeException──────────┐
│ Index was outside the bounds of the array. │
└────────────────────────────────────────────┘

5.4.10. Reversed String Return#

reversed. Logically, you will perform two separate ideas: reversing a string and printing it. Now consider the first part as its own method:

// this is a method return a string `s` in reverse order.
// say, if s is "drab", return "bard".
// below is the possible form of the header for the method
static string Reverse (string s)

In the Reverse method, use a for loop:

for (int i = s.Length - 1; i >= 0; i--) {

A significant idea here is that, instead of immediately printing the char’s, you need to return a reversed string. That means, you need to create a single string, with all the characters, before returning the result.

Let us think about this: If you start with s as "drab", and you go through the letters one at a time in reverse order, b a r d, you build up successively:

b
ba
bar
bard

You need a loop with variables and operations. The sequence of reversed letters, s[i], are the last character on the end of each line above.

We need a name for the initial part. I used the name rev. Combining with a string is done with the + operator. Then when rev is "ba" and s[i] is 'r', the combination, using the variable names, is

rev + s[i]

We want this in our loop, so we must be able to use that expression each time through the loop, so rev changes each time through the loop. In the next iteration rev is the result of the previous expression. The assignment statement to give us the next version of rev can just be:

int i = 2;
int rev = 0;
int[] s = { 3, 7, 1, 9, 4 };
rev = rev + s[i];

That gives us the general rule. Pay attention now to the beginning and end: The end is simple: The last value for rev is the complete reversed string, so that is what we return.

How do we initialize rev? You could imagine rev starting as "b", but the the first character that we add is 'a', and we would not be going through all the characters in our loop. It is better to go all the way back to the beginning: If we use the general form with the first letter in the reversed sequence,

int i = 2;
int rev = 0;
int[] s = { 3, 7, 1, 9, 4 };
rev = rev + s[i];

then the result of the initial rev + 'b' should just be "b". So what would rev be?

Remember the empty string: initialize rev to be "".

The result is:

/// Return s in reverse order.
/// If s is "drab", return "bard".
static string Reverse (string s)
{
   string rev = "";
   for (int i = s.Length - 1; i >= 0; i--) {
      rev += s[i];
   }
   return rev;
}

We used our new operator += to be more concise.

This function and a Main used to demonstrate it are in here.