{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "63fb57db",
   "metadata": {},
   "source": [
    "(io)=\n",
    "\n",
    "# Input and Output\n",
    "\n",
    "% ReadKey\n",
    "\n",
    "% tip::¶\n",
    "%\n",
    "% Save the file before ``dotnet run``.\n",
    "% Use ``dotnet build`` or ``dotnet build`` *ProjectName* when needed.\n",
    "\n",
    "```{index} Console; ReadLine\n",
    "```\n",
    "\n",
    "(read-from-console)=\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d078fc28",
   "metadata": {},
   "source": [
    "## Input: Reading from the Keyboard\n",
    "\n",
    "At console or terminal, input is done in two parts: Prompt and read.\n",
    "Because the lack of better visual cues, we use a *prompt* to instruct the user\n",
    "how to respond. For example:\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "23708432",
   "metadata": {
    "language_info": {
     "name": "polyglot-notebook"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    },
    "vscode": {
     "languageId": "polyglot-notebook"
    }
   },
   "outputs": [],
   "source": [
    "Console.Write(\"Enter your name: \");\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "67297efb",
   "metadata": {},
   "source": [
    "\n",
    "The user input from keyboard is automatically shown\n",
    "in the terminal or console window. For a program to take in the characters typed,\n",
    "another method in the `Console` class is used:\n",
    "`Console.ReadLine`.\n",
    "\n",
    "The read method reads the data from a line typed at the keyboard by the user.\n",
    "When the user presses the Enter (Return) key, the sequence of characters,\n",
    "form the string *value* of the read method.\n",
    "\n",
    "With any method producing a value, the value is *lost* unless it\n",
    "is *immediately* used. We therefore assign the value from the read method\n",
    "to a variable like in\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "27cc1ae8",
   "metadata": {
    "language_info": {
     "name": "polyglot-notebook"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    },
    "vscode": {
     "languageId": "polyglot-notebook"
    }
   },
   "outputs": [],
   "source": [
    "string name;                                // declare variable\n",
    "\n",
    "Console.WriteLine(\"Enter your name: \");     // prompt for input\n",
    "name = Console.ReadLine();                  // save value to variable\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "57cc352b",
   "metadata": {},
   "source": [
    "\n",
    "or read in one line\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "23fbc7d9",
   "metadata": {
    "language_info": {
     "name": "polyglot-notebook"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    },
    "vscode": {
     "languageId": "polyglot-notebook"
    }
   },
   "outputs": [],
   "source": [
    "Console.WriteLine(\"Enter your name: \");\n",
    "string name = Console.ReadLine();\n",
    "\n",
    "Console.WriteLine(name);                    // print to test\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "155e38f8",
   "metadata": {},
   "source": [
    "Now we have a variable containing the value for us to operate on."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7e95c7cf",
   "metadata": {},
   "source": [
    "```{index} string; Parse\n",
    "```\n",
    "\n",
    "(the-ui-class)=\n",
    "\n",
    "## User Input: The UI class\n",
    "\n",
    "Andrew N. Harrington and George Thiruvathukal (2021) have prepared some useful\n",
    "C# utility methods for convenient user input and the code is available on [github](https://github.com/LoyolaChicagoBooks/introcs-csharp-examples/blob/master/ui/ui.cs).\n",
    "\n",
    "To use the code, go to the github repository, and do the following:\n",
    "\n",
    "1. Make sure the path is `introcs-csharp-examples/ui/ui.cs` and the file name is `ui.cs`.\n",
    "2. Make sure the *Code* tab is selected and you are seeing the source code.\n",
    "3. Use `copy raw files` icon or simply highlight the whole code.\n",
    "4. In your project folder, create a new file and name it `ui.cs`.\n",
    "5. Paste the copied code to the file.\n",
    "6. Change the namespace of the file from IntroCS to `IntroCSCS`.\n",
    "\n",
    "Alternatively, you may just download `ui.cs` as a raw file from github and place it in the\n",
    "project folder with the Program.cs file and change the file's namespace from IntroCS\n",
    "to IntroCSCS.\n",
    "\n",
    "Now you can use the input methods in your code. For example, you may use its\n",
    "`PromptInt` method to prompting a user input of integer type:\n",
    "\n",
    "```{note}\n",
    "Notice that `ui.cs` is added alongside `Program.cs` in the **same project folder** — this works because a project can contain many `.cs` files. Remember: **one entry point (the `Main()` method) per project, but a project can have many `.cs` files.**\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0466f52f",
   "metadata": {
    "language_info": {
     "name": "polyglot-notebook"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    },
    "vscode": {
     "languageId": "polyglot-notebook"
    }
   },
   "outputs": [],
   "source": [
    "a = UI.PromptInt(\"Enter integer leg: \");\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ffa70c4d",
   "metadata": {},
   "source": [
    "## Casting (Type Conversion) in Input\n",
    "\n",
    "The default value from `Console.ReadLine()` is of string type and\n",
    "when we want the user to supply numbers, we need to explicitly convert the\n",
    "strings to the proper kind of number. We cannot convert the string type to\n",
    "int implicitly because strings are immutable in C#. Instead, you need to parse\n",
    "the string and assign to the intended data type.\n",
    "\n",
    "There are C# built-in methods to do that. `int.Parse` takes a string parameter\n",
    "that should be the characters in an `int`, like \"123\" or \"-25\", and\n",
    "produces the corresponding `int` value, like 123 or -25:\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2239a9b4",
   "metadata": {
    "language_info": {
     "name": "polyglot-notebook"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    },
    "vscode": {
     "languageId": "polyglot-notebook"
    }
   },
   "outputs": [],
   "source": [
    "Console.WriteLine(\"Enter your age: \");      // prompt\n",
    "var ageInput = Console.ReadLine();          // save input to variable\n",
    "\n",
    "Console.WriteLine(ageInput.GetType());      // check type: string\n",
    "Console.WriteLine(ageInput);\n",
    "\n",
    "int age = int.Parse(ageInput);               // casting type to int\n",
    "\n",
    "Console.WriteLine(age.GetType());\n",
    "Console.WriteLine(age);\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "98e2cff1",
   "metadata": {},
   "source": [
    "\n",
    "The double type works similarly as the int type:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "30b29485",
   "metadata": {
    "language_info": {
     "name": "polyglot-notebook"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    },
    "vscode": {
     "languageId": "polyglot-notebook"
    }
   },
   "outputs": [],
   "source": [
    "string s = \"34.5\";\n",
    "double d = double.Parse(s);\n",
    "d"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8cf2aa6c",
   "metadata": {},
   "source": [
    "or, in VS Code:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "05cd7489",
   "metadata": {
    "language_info": {
     "name": "polyglot-notebook"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    },
    "vscode": {
     "languageId": "polyglot-notebook"
    }
   },
   "outputs": [],
   "source": [
    "string s = \"34.5\";\n",
    "double d = double.Parse(s);\n",
    "Console.WriteLine(d);\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "eea2862f",
   "metadata": {},
   "source": [
    "(substitution-in-writeline)=\n",
    "\n",
    "## Console.WriteLine()\n",
    "\n",
    "The method `Console.Write()` does not create a new line when executing.\n",
    "We can make use of this in cases such as reading user input\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a5d3a125",
   "metadata": {
    "language_info": {
     "name": "polyglot-notebook"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    },
    "vscode": {
     "languageId": "polyglot-notebook"
    }
   },
   "outputs": [],
   "source": [
    "string firstName;\n",
    "\n",
    "Console.Write(\"Enter you first name: \");    // input will start here\n",
    "firstName = Console.ReadLine();\n",
    "\n",
    "Console.WriteLine(\"Hiya, \" + firstName + \"!\");\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c590ea7f",
   "metadata": {},
   "source": [
    "\n",
    "You have seen output (\"print\" or \"echo\") from the very beginning when creating\n",
    "the console app project (`dotnet console new`) and see the executing line of:\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d9830684",
   "metadata": {
    "language_info": {
     "name": "polyglot-notebook"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    },
    "vscode": {
     "languageId": "polyglot-notebook"
    }
   },
   "outputs": [],
   "source": [
    "Console.WriteLine(\"Hello, World\");\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "410610be",
   "metadata": {},
   "source": [
    "\n",
    "Naturally, we can print variables in addition to the string literal. For example,\n",
    "extending our input code:\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "253d404e",
   "metadata": {
    "language_info": {
     "name": "polyglot-notebook"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    },
    "vscode": {
     "languageId": "polyglot-notebook"
    }
   },
   "outputs": [],
   "source": [
    "Console.WriteLine(\"Enter your name: \");\n",
    "string name = Console.ReadLine();\n",
    "\n",
    "Console.WriteLine(\"Hello,\" + name);        // use + for concatenation\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "67259e24",
   "metadata": {},
   "source": [
    "(format-strings)=\n",
    "\n",
    "## Composite formatting\n",
    "\n",
    "Instead of using the `+` operator, **composite format** (the\n",
    "\"fill-in-the-braces\") gives us better control over output using `Console.WriteLine`\n",
    "by using positional **string format index** to separate the string and the data variables.\n",
    "\n",
    "In composite formatting, you use two arguments: 1) a composite format **string** with\n",
    "**parameter specifier** (`format item` index) and 2) an **object list**. When printing,\n",
    "the objects (variables or literal values) substitute the parameter specifiers one by one.\n",
    "\n",
    "Observe the last two statements:\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c9d667a6",
   "metadata": {
    "language_info": {
     "name": "polyglot-notebook"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    },
    "vscode": {
     "languageId": "polyglot-notebook"
    }
   },
   "outputs": [],
   "source": [
    "string firstName;\n",
    "\n",
    "Console.Write(\"Enter you first name: \");    // input will start here\n",
    "firstName = Console.ReadLine();\n",
    "\n",
    "Console.WriteLine(\"Hiya, \" + firstName + \"!\");\n",
    "Console.WriteLine(\"Hiya, {0}!\", firstName);\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e51cf26a",
   "metadata": {},
   "source": [
    "\n",
    "You can imagine that there would be \\{1}, \\{2}... like this:\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7b14dedb",
   "metadata": {
    "language_info": {
     "name": "polyglot-notebook"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    },
    "vscode": {
     "languageId": "polyglot-notebook"
    }
   },
   "outputs": [],
   "source": [
    "Console.WriteLine(\"Hiya, {0} {1}!\", firstName, lastName);\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3a33f61f",
   "metadata": {},
   "source": [
    "\n",
    "With composite formatting, we have the flexibility of writing the output string\n",
    "and place the variables anywhere we prefer in the string.\n",
    "\n",
    "A more elaborate silly examples that you could test in csharp would be:\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2c1f5388",
   "metadata": {
    "language_info": {
     "name": "polyglot-notebook"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    },
    "vscode": {
     "languageId": "polyglot-notebook"
    }
   },
   "outputs": [],
   "source": [
    "string first = \"Peter\";\n",
    "string last = \"Piper\";\n",
    "string what = \"pick\";\n",
    "Console.WriteLine(\"{0} {1}, {0} {1}, {2}.\", first, last, what);\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9173557a",
   "metadata": {},
   "source": [
    "\n",
    "It would print:\n",
    "\n",
    "```\n",
    "Peter Piper, Peter Piper, pick.\n",
    "```\n",
    "\n",
    "where parameter 0 is `first` (value `\"Peter\"`),\n",
    "parameter 1 is `last` ( value `\"Piper\"`), and\n",
    "parameter 2 is `what` (value `\"pick\"`).\n",
    "\n",
    "As an example, try the following in csharprepl:\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5b106162",
   "metadata": {
    "language_info": {
     "name": "polyglot-notebook"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    },
    "vscode": {
     "languageId": "polyglot-notebook"
    }
   },
   "outputs": [],
   "source": [
    "int x = 7;\n",
    "int y = 5;\n",
    "Console.WriteLine(\"{0} plus {1} is {2}; {0} times {1} is {3}.\", x, y, x+y, x*y);\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "39c4ce0e",
   "metadata": {},
   "source": [
    "\n",
    "to see it prints:\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6f282347",
   "metadata": {
    "language_info": {
     "name": "polyglot-notebook"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    },
    "vscode": {
     "languageId": "polyglot-notebook"
    }
   },
   "outputs": [],
   "source": [
    "7 plus 5 is 12; 7 times 5 is 35.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c5a5ff2e",
   "metadata": {},
   "source": [
    "\n",
    "Note the following features of the parameters after the first string:\n",
    "\n",
    "- These parameters can be any expression,\n",
    "  and the expressions get evaluated before printing.\n",
    "- These parameters to be substituted can be of any type.\n",
    "- These parameters are automatically converted to a string form, just as in the\n",
    "  use of the string `+` operation.\n",
    "\n",
    "In fact the simple use of format strings shown so far can be completed replaced by\n",
    "long expressions with `+`, if that is your taste."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c3733be9",
   "metadata": {},
   "source": [
    "### Format Specifiers\n",
    "\n",
    "In addition to printing out strings using composite formatting as seen above, a common\n",
    "way to format strings is using the string.Format() method to save the value of the\n",
    "variable into another string. For example, we may save a format string to a variable:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6e07b3dc",
   "metadata": {
    "language_info": {
     "name": "polyglot-notebook"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    },
    "vscode": {
     "languageId": "polyglot-notebook"
    }
   },
   "outputs": [],
   "source": [
    "var msg = string.Format(\"There are {0} balls\", 3);\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9f6b8414",
   "metadata": {},
   "source": [
    "\n",
    "Also, C# has **format specifiers** [^format-specifiers-1] for different data types when\n",
    "formatting data.\n",
    "For example, `D` for Decimal type:\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6b64cabf",
   "metadata": {
    "language_info": {
     "name": "polyglot-notebook"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    },
    "vscode": {
     "languageId": "polyglot-notebook"
    }
   },
   "outputs": [],
   "source": [
    "int value = 6324;\n",
    "string output = string.Format(\"{{{0:D}}}\", value);\n",
    "\n",
    "Console.WriteLine(output);\n",
    "// The example displays the following output:\n",
    "//       {6324}\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b0aa66ae",
   "metadata": {},
   "source": [
    "\n",
    "You may format two strings together. In the example below, the `{1,6:D}`\n",
    "format item takes the second item, format it also as a decimal and the\n",
    "string length will be 6 characters (right-aligned and padded with empty strings;\n",
    "the 6 here is the `alignment component`):\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ac1cbad5",
   "metadata": {
    "language_info": {
     "name": "polyglot-notebook"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    },
    "vscode": {
     "languageId": "polyglot-notebook"
    }
   },
   "outputs": [],
   "source": [
    "string.Format(\"{0:D}  {1,6:D}\", 634, 868); // result: 634     868\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ed7e02f6",
   "metadata": {},
   "source": [
    "\n",
    "`C` for currency:\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "212a60af",
   "metadata": {
    "language_info": {
     "name": "polyglot-notebook"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    },
    "vscode": {
     "languageId": "polyglot-notebook"
    }
   },
   "outputs": [],
   "source": [
    "int myNumber = 100;\n",
    "Console.WriteLine(\"{0:C}\", myNumber);\n",
    "\n",
    "// The example displays the following output\n",
    "// if en-US is the current culture:\n",
    "//        $100.00\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4744c355",
   "metadata": {},
   "source": [
    "(string-interpolation)=\n",
    "\n",
    "## String Interpolation\n",
    "\n",
    "The `$` character identifies a string literal as an **interpolated string**. An interpolated\n",
    "string is a string literal that might contain interpolation expressions. When an\n",
    "interpolated string is resolved to a result string, the compiler replaces items with\n",
    "interpolation expressions by the string representations of the expression results.\n",
    "String interpolation provides a more readable, convenient syntax to format strings.\n",
    "To identify a string literal as an interpolated string, prepend it with the `$` symbol.\n",
    "\n",
    "Compare **composite formatting** and **string interpolation**:\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "869388cf",
   "metadata": {
    "language_info": {
     "name": "polyglot-notebook"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    },
    "vscode": {
     "languageId": "polyglot-notebook"
    }
   },
   "outputs": [],
   "source": [
    "var name = \"Mark\";\n",
    "var date = DateTime.Now;\n",
    "\n",
    "// Composite formatting:\n",
    "Console.WriteLine(\"Hello, {0}! Today is {1}, it's {2:HH:mm} now.\", name, date.DayOfWeek, date);\n",
    "// String interpolation:\n",
    "Console.WriteLine($\"Hello, {name}! Today is {date.DayOfWeek}, it's {date:HH:mm} now.\");\n",
    "// Both calls produce the same output that is similar to:\n",
    "// Hello, Mark! Today is Wednesday, it's 19:40 now.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ec0fbacf",
   "metadata": {},
   "source": [
    "## Writing to the Console\n",
    "\n",
    "In csharprepl, you can type an expression and immediately see the result\n",
    "of its evaluation. This is good for test out syntax. In a regular C# program\n",
    "run from a file like in VS Code, you must explicitly give instructions to print to a\n",
    "console/terminal.\n",
    "\n",
    "This printing is accomplished through a method with a long name: `Console.WriteLine`.\n",
    "Like with math, you can pass a method a value to work on, by placing it in\n",
    "parentheses after the name of the method.\n",
    "\n",
    "`Console` is a C# class maintained by the system, that\n",
    "interacts with the terminal or console window where text output\n",
    "appears for the program. A method defined in that class is `WriteLine`.\n",
    "To refer to a method like `WriteLine` in a different class, you must indicate\n",
    "the location of the method with the \"dot\" notation shown:\n",
    "class name, then `.`, then the method. This\n",
    "gives the more elaborate name needed in the program.\n",
    "\n",
    "```{index} Console; Write\n",
    "```\n",
    "\n",
    "The `Console.WriteLine` method automatically makes the printing\n",
    "position advance to the next line, as when you press the Enter or Return key.\n",
    "A variant, `Console.Write`, prints the parameter exactly, and nothing else.\n",
    "\n",
    "```{rubric} Footnotes\n",
    "```\n",
    "\n",
    "[^format-specifiers-1]: [.NET Standard numeric format strings](https://learn.microsoft.com/en-us/dotnet/standard/base-types/standard-numeric-format-strings)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2ddb952d",
   "metadata": {},
   "source": [
    "## Table Formatting with Loop Output\n",
    "\n",
    "The following examples were moved from iteration worked examples to keep formatting topics centralized in Input/Output.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d06c5fdc",
   "metadata": {},
   "source": [
    "## Format Output: Console.Write()\n",
    "\n",
    "Thus far all of our `for` loops have used a sequence of successive integers.\n",
    "You can do a quick test in `csharprepl` like:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "175cc166",
   "metadata": {
    "language_info": {
     "name": "polyglot-notebook"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    },
    "vscode": {
     "languageId": "polyglot-notebook"
    }
   },
   "outputs": [],
   "source": [
    "for (int i = 1; i < 5; i++)\n",
    " {\n",
    "    Console.WriteLine(i);\n",
    " }"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ecb94a68",
   "metadata": {},
   "source": [
    "Now let us make the output neater by using the format string ({ref}`format-strings`) and\n",
    "the `Console.Write()` method:"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "89711ec2",
   "metadata": {},
   "source": [
    "(left-justification)=\n",
    "\n",
    "## Formatting Tables\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8b93a4ec",
   "metadata": {},
   "source": [
    "\n",
    "Reports commonly include tables, often with successive lines generated by\n",
    "a consistent formula and therefore a good example for coding. As a simple first table, we can show the square,\n",
    "cube, and square root of numbers 1 through 10.\n",
    "The Math class has a method `Sqrt`, so we take the square root with the `Math.Sqrt`\n",
    "method. The pattern is consistent, so we can loop easily:\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "17923016",
   "metadata": {
    "language_info": {
     "name": "polyglot-notebook"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    },
    "vscode": {
     "languageId": "polyglot-notebook"
    }
   },
   "outputs": [],
   "source": [
    "for ( int n = 1; n <= 10; n++)\n",
    "{\n",
    "    Console.WriteLine(\"{0} {1} {2} {3}\", n, n*n, n*n*n, Math.Sqrt(n));\n",
    "}\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f30fec3f",
   "metadata": {},
   "source": [
    "\n",
    "The numbers will be there, but the output is not pretty:\n",
    "\n",
    "```none\n",
    "1 1 1 1\n",
    "2 4 8 1.4142135623731\n",
    "3 9 27 1.73205080756888\n",
    "4 16 64 2\n",
    "5 25 125 2.23606797749979\n",
    "6 36 216 2.44948974278318\n",
    "7 49 343 2.64575131106459\n",
    "8 64 512 2.82842712474619\n",
    "9 81 729 3\n",
    "10 100 1000 3.16227766016838\n",
    "```\n",
    "\n",
    "First we might not need all those digits in the square root approximations.\n",
    "We can replace `{3}` by `{3:F4}` to just show 4 decimal places.\n",
    "\n",
    "We can adjust the spacing to make nice\n",
    "columns by using a further formatting option. The longest entries are all\n",
    "in the last row, where they take up, 2, 3, 4, and 6 columns (for 3.1623).\n",
    "Change the format string:\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "22156745",
   "metadata": {
    "language_info": {
     "name": "polyglot-notebook"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    },
    "vscode": {
     "languageId": "polyglot-notebook"
    }
   },
   "outputs": [],
   "source": [
    "for ( int n = 1; n <= 10; n++) {\n",
    "    Console.WriteLine(\"{0,2} {1,3} {2,4} {3,6:F4}\",\n",
    "                       n, n*n, n*n*n, Math.Sqrt(n));\n",
    "}\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1fa540c3",
   "metadata": {},
   "source": [
    "\n",
    "and we generate the neater output:\n",
    "\n",
    "```none\n",
    " 1   1    1 1.0000\n",
    " 2   4    8 1.4142\n",
    " 3   9   27 1.7321\n",
    " 4  16   64 2.0000\n",
    " 5  25  125 2.2361\n",
    " 6  36  216 2.4495\n",
    " 7  49  343 2.6458\n",
    " 8  64  512 2.8284\n",
    " 9  81  729 3.0000\n",
    "10 100 1000 3.1623\n",
    "```\n",
    "\n",
    "We are using two new formatting forms:\n",
    "\n",
    "> `{`\n",
    ">\n",
    "> index\n",
    ">\n",
    "> `,`\n",
    ">\n",
    "> fieldWidth\n",
    ">\n",
    "> `}`\n",
    ">\n",
    ">  and\n",
    ">\n",
    "> `{`\n",
    ">\n",
    "> index\n",
    ">\n",
    "> `,`\n",
    ">\n",
    "> fieldWidth\n",
    ">\n",
    "> `:F`\n",
    ">\n",
    "> #\n",
    ">\n",
    "> `}`\n",
    "\n",
    "where index, fieldWidth, and # are replaces by specific literal integers.\n",
    "The new part with the comma (not colon) and fieldWidth, sets the *minimum*\n",
    "number of columns used for the substituted string, padding with blanks as needed.\n",
    "\n",
    "*If the string to be inserted is wider than the fieldWidth,*\n",
    "then the *whole* string is inserted, *ignoring* the fieldWidth. For example:\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fabe71ea",
   "metadata": {
    "language_info": {
     "name": "polyglot-notebook"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    },
    "vscode": {
     "languageId": "polyglot-notebook"
    }
   },
   "outputs": [],
   "source": [
    "string s = \"stuff\";\n",
    "Console.WriteLine(\"123456789\");\n",
    "Console.WriteLine(\"{0,9}\\n{0,7}\\n{0,5}\\n{0,3}\", s);\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "804b7d63",
   "metadata": {},
   "source": [
    "\n",
    "generates:\n",
    "\n",
    "```none\n",
    "123456789\n",
    "    stuff\n",
    "  stuff\n",
    "stuff\n",
    "stuff\n",
    "```\n",
    "\n",
    "filling 9, 7, and then 5 columns, by padding with 4, 2, and 0 blanks.\n",
    "*The last line sticks out past the proposed 3-column fieldWidth.*\n",
    "\n",
    "One more thing to add to our power table is a heading. We might want:\n",
    "\n",
    "```none\n",
    "n   square    cube    root\n",
    "```\n",
    "\n",
    "To make the data line up with the heading titles,\n",
    "we can expand the columns, with code in example:\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "67e9a688",
   "metadata": {
    "language_info": {
     "name": "polyglot-notebook"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    },
    "vscode": {
     "languageId": "polyglot-notebook"
    }
   },
   "outputs": [],
   "source": [
    "Console.WriteLine(\"{0,2}{1,7}{2,5}{3,7}\",\n",
    "              \"n\", \"square\", \"cube\", \"root\");\n",
    "for ( int n = 1; n <= 10; n++) {\n",
    "Console.WriteLine(\"{0,2}{1,7}{2,5}{3,7:F4}\",\n",
    "                    n, n*n, n*n*n, Math.Sqrt(n));\n",
    "}\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d3033ed9",
   "metadata": {},
   "source": [
    "\n",
    "generating the output:\n",
    "\n",
    "```none\n",
    " n  square    cube    root\n",
    " 1       1       1  1.0000\n",
    " 2       4       8  1.4142\n",
    " 3       9      27  1.7321\n",
    " 4      16      64  2.0000\n",
    " 5      25     125  2.2361\n",
    " 6      36     216  2.4495\n",
    " 7      49     343  2.6458\n",
    " 8      64     512  2.8284\n",
    " 9      81     729  3.0000\n",
    "10     100    1000  3.1623\n",
    "```\n",
    "\n",
    "Note how we make sure the columns are consistent in the heading and further rows:\n",
    "We used a format string for the headings with the same field widths as\n",
    "in the body of the table. A separate variation: We also reduced the length\n",
    "of the format string by putting all the substitution expressions in braces\n",
    "right beside each other, and generate the space between columns with a\n",
    "larger field width.\n",
    "\n",
    "```\n"
   ]
  }
 ],
 "metadata": {
  "jupytext": {
   "cell_metadata_filter": "-all",
   "main_language": "python",
   "notebook_metadata_filter": "-all"
  },
  "kernelspec": {
   "display_name": ".NET (C#)",
   "language": "C#",
   "name": ".net-csharp"
  },
  "language_info": {
   "name": "csharp"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
