CSCS1730 UNIX/Linux Fundamentals
PROJECT: PROCESSING WARRANTED NUMBERS (pwn1)
Part 2 of 2 (builds directly on pwn0)
TOOLBOX
In addition to the tools you're already familiar with, it is recommended you check out the following tools for possible application in this project (you may not need to use them in your solution, but they definitely offer up functionality that some solutions can make use of):
- bc(1)
- comm(1)
- diff(1)
- grep(1)
- join(1)
- printf(1)
- seq(1)
- sort(1)
- uniq(1)
Don't forget the manual pages for bash(1) itself (see the sections on arithmetic evaluation, parameter expansion, and conditional expressions). Reading manual pages to discover capabilities is part of the exercise.
For this project in particular, give bc(1) a good look (its obase
setting is a natural fit for converting to an arbitrary base), and consider
how sort(1) and uniq(1) could help tidy up a list of bases.
REFERENCE
For additional information on the printf(1) tool recommended for use in this project, please check out this paper:
- https://lab46.g7n.org/downloads/printf.pdf
NOTE that while it focuses on the C and Perl variants of printf, the conceptual underpinnings are the same, and many of the examples are likely portable to the UNIX variant of the tool.
OBJECTIVE
To complete the script begun in pwn0: a script that can, with or without information provided by the user, display useful reference data in various number bases, skipping through values, adding bases, removing bases, and standing up to bad input.
Your finished pwn1.sh does everything described in this document and in pwn0. Begin from your own pwn0.sh. If your pwn0 had gaps, this is your chance to close them: pwn1 is evaluated against the whole script.
BACKGROUND
In pwn0 you built the foundation: a table of values in bases 2, 8, 10, and 16, with a starting and ending value, forward or backward, bounds checking, and online help. The four bases were fixed, and so was the step of 1.
For pwn1, the table becomes flexible. Everything about it is decided at run time:
- how far apart consecutive values are (by#)
- which bases appear (with# to add, sans# to remove, even the defaults)
- how gracefully the script copes with arguments that make no sense
Where pwn0 had four columns written out in your logic, pwn1 has a list of bases that your script assembles, and that the header, the divider, and every row are built from. That shift (from "four things" to "a list of things") is the heart of this project.
PROCESS
Your script does everything pwn0 did. As a reminder, with no arguments:
lab46:~/src/SEMESTER/unix/pwn1$ ./pwn1.sh
base 2 | base 8 | base10 | base16 |
----------+----------+----------+----------+
0 | 0 | 0 | 0 |
1 | 1 | 1 | 1 |
10 | 2 | 2 | 2 |
11 | 3 | 3 | 3 |
100 | 4 | 4 | 4 |
101 | 5 | 5 | 5 |
110 | 6 | 6 | 6 |
111 | 7 | 7 | 7 |
1000 | 10 | 8 | 8 |
1001 | 11 | 9 | 9 |
1010 | 12 | 10 | A |
1011 | 13 | 11 | B |
1100 | 14 | 12 | C |
1101 | 15 | 13 | D |
1110 | 16 | 14 | E |
1111 | 17 | 15 | F |
lab46:~/src/SEMESTER/unix/pwn1$
The full set of arguments your script should take:
- $1- starting value (a whole number, in decimal)
- $2- ending value (a whole number, in decimal)
Numerical arguments are to be given in decimal.
Additional arguments your script should support:
- by# - iterate through values by # (default: 1)
- with# - include base # in the list of bases to display
- sans# - remove base # in the list of bases to display
- help - display script usage and exit
With any of these arguments validly provided, they should adjust the script's processing and output accordingly. Any of them may be combined with any other, in any order.
Some additional constraints/assumptions you can make:
- the minimum lower limit your script should process for is 0. If an input goes negative, cap it to 0.
- the maximum upper limit you can implement for is 255 (base 10). If an input goes in excess of this, cap it to 255.
- valid bases are 2 through 16, inclusive. The default bases are 2, 8, 10, and 16.
Examples of the pwn0 behaviors (start-only, start/end, going backward, and exceeding bounds) are in the pwn0 project document; they all still apply.
SKIPPING VALUES
With the 'by#' argument, we can cause numbers to iterate by more than 1. For example, if we wanted to go from 3 to 81 skipping 3 values each turn:
lab46:~/src/SEMESTER/unix/pwn1$ ./pwn1.sh 3 81 by3
base 2 | base 8 | base10 | base16 |
----------+----------+----------+----------+
11 | 3 | 3 | 3 |
110 | 6 | 6 | 6 |
1001 | 11 | 9 | 9 |
1100 | 14 | 12 | C |
1111 | 17 | 15 | F |
10010 | 22 | 18 | 12 |
10101 | 25 | 21 | 15 |
11000 | 30 | 24 | 18 |
11011 | 33 | 27 | 1B |
11110 | 36 | 30 | 1E |
100001 | 41 | 33 | 21 |
100100 | 44 | 36 | 24 |
100111 | 47 | 39 | 27 |
101010 | 52 | 42 | 2A |
101101 | 55 | 45 | 2D |
110000 | 60 | 48 | 30 |
110011 | 63 | 51 | 33 |
110110 | 66 | 54 | 36 |
111001 | 71 | 57 | 39 |
111100 | 74 | 60 | 3C |
111111 | 77 | 63 | 3F |
1000010 | 102 | 66 | 42 |
1000101 | 105 | 69 | 45 |
1001000 | 110 | 72 | 48 |
1001011 | 113 | 75 | 4B |
1001110 | 116 | 78 | 4E |
1010001 | 121 | 81 | 51 |
lab46:~/src/SEMESTER/unix/pwn1$
This should be flexible whether going forward or backward in count:
lab46:~/src/SEMESTER/unix/pwn1$ ./pwn1.sh 32 2 by4
base 2 | base 8 | base10 | base16 |
----------+----------+----------+----------+
100000 | 40 | 32 | 20 |
11100 | 34 | 28 | 1C |
11000 | 30 | 24 | 18 |
10100 | 24 | 20 | 14 |
10000 | 20 | 16 | 10 |
1100 | 14 | 12 | C |
1000 | 10 | 8 | 8 |
100 | 4 | 4 | 4 |
lab46:~/src/SEMESTER/unix/pwn1$
ADDITIONAL BASES
Your script should also support the inclusion of additional bases (valid bases are any base between 2 and 16, inclusive). The default bases assumed included are 2, 8, 10, and 16, but additional ones may be specified with a with# argument.
For instance, let's say we wanted to include base 7:
lab46:~/src/SEMESTER/unix/pwn1$ ./pwn1.sh with7
base 2 | base 7 | base 8 | base10 | base16 |
----------+----------+----------+----------+----------+
0 | 0 | 0 | 0 | 0 |
1 | 1 | 1 | 1 | 1 |
10 | 2 | 2 | 2 | 2 |
11 | 3 | 3 | 3 | 3 |
100 | 4 | 4 | 4 | 4 |
101 | 5 | 5 | 5 | 5 |
110 | 6 | 6 | 6 | 6 |
111 | 10 | 7 | 7 | 7 |
1000 | 11 | 10 | 8 | 8 |
1001 | 12 | 11 | 9 | 9 |
1010 | 13 | 12 | 10 | A |
1011 | 14 | 13 | 11 | B |
1100 | 15 | 14 | 12 | C |
1101 | 16 | 15 | 13 | D |
1110 | 20 | 16 | 14 | E |
1111 | 21 | 17 | 15 | F |
lab46:~/src/SEMESTER/unix/pwn1$
And this should work even with the potential inclusion of starting, ending, or a by# option (forward or backward):
lab46:~/src/SEMESTER/unix/pwn1$ ./pwn1.sh 13 255 by13 with7
base 2 | base 7 | base 8 | base10 | base16 |
----------+----------+----------+----------+----------+
1101 | 16 | 15 | 13 | D |
11010 | 35 | 32 | 26 | 1A |
100111 | 54 | 47 | 39 | 27 |
110100 | 103 | 64 | 52 | 34 |
1000001 | 122 | 101 | 65 | 41 |
1001110 | 141 | 116 | 78 | 4E |
1011011 | 160 | 133 | 91 | 5B |
1101000 | 206 | 150 | 104 | 68 |
1110101 | 225 | 165 | 117 | 75 |
10000010 | 244 | 202 | 130 | 82 |
10001111 | 263 | 217 | 143 | 8F |
10011100 | 312 | 234 | 156 | 9C |
10101001 | 331 | 251 | 169 | A9 |
10110110 | 350 | 266 | 182 | B6 |
11000011 | 366 | 303 | 195 | C3 |
11010000 | 415 | 320 | 208 | D0 |
11011101 | 434 | 335 | 221 | DD |
11101010 | 453 | 352 | 234 | EA |
11110111 | 502 | 367 | 247 | F7 |
lab46:~/src/SEMESTER/unix/pwn1$
Multiple additional bases can be included… you merely append additional with# arguments:
lab46:~/src/SEMESTER/unix/pwn1$ ./pwn1.sh 196 2 with3 by14 with12
base 2 | base 3 | base 8 | base10 | base12 | base16 |
----------+----------+----------+----------+----------+----------+
11000100 | 21021 | 304 | 196 | 144 | C4 |
10110110 | 20202 | 266 | 182 | 132 | B6 |
10101000 | 20020 | 250 | 168 | 120 | A8 |
10011010 | 12201 | 232 | 154 | 10A | 9A |
10001100 | 12012 | 214 | 140 | B8 | 8C |
1111110 | 11200 | 176 | 126 | A6 | 7E |
1110000 | 11011 | 160 | 112 | 94 | 70 |
1100010 | 10122 | 142 | 98 | 82 | 62 |
1010100 | 10010 | 124 | 84 | 70 | 54 |
1000110 | 2121 | 106 | 70 | 5A | 46 |
111000 | 2002 | 70 | 56 | 48 | 38 |
101010 | 1120 | 52 | 42 | 36 | 2A |
11100 | 1001 | 34 | 28 | 24 | 1C |
1110 | 112 | 16 | 14 | 12 | E |
lab46:~/src/SEMESTER/unix/pwn1$
OMITTING BASES
With the sans# option, we can leave out specified bases (useful for excluding any of the default 2, 8, 10, or 16).
Here we will omit base 8 from a default run:
lab46:~/src/SEMESTER/unix/pwn1$ ./pwn1.sh sans8
base 2 | base10 | base16 |
----------+----------+----------+
0 | 0 | 0 |
1 | 1 | 1 |
10 | 2 | 2 |
11 | 3 | 3 |
100 | 4 | 4 |
101 | 5 | 5 |
110 | 6 | 6 |
111 | 7 | 7 |
1000 | 8 | 8 |
1001 | 9 | 9 |
1010 | 10 | A |
1011 | 11 | B |
1100 | 12 | C |
1101 | 13 | D |
1110 | 14 | E |
1111 | 15 | F |
lab46:~/src/SEMESTER/unix/pwn1$
Of course, this option can be validly mixed with any of the other valid options, and needs to work as appropriate (here you'll see a run we did prior, with the only difference being the omission of base 8):
lab46:~/src/SEMESTER/unix/pwn1$ ./pwn1.sh 196 2 with3 by14 with12 sans8
base 2 | base 3 | base10 | base12 | base16 |
----------+----------+----------+----------+----------+
11000100 | 21021 | 196 | 144 | C4 |
10110110 | 20202 | 182 | 132 | B6 |
10101000 | 20020 | 168 | 120 | A8 |
10011010 | 12201 | 154 | 10A | 9A |
10001100 | 12012 | 140 | B8 | 8C |
1111110 | 11200 | 126 | A6 | 7E |
1110000 | 11011 | 112 | 94 | 70 |
1100010 | 10122 | 98 | 82 | 62 |
1010100 | 10010 | 84 | 70 | 54 |
1000110 | 2121 | 70 | 5A | 46 |
111000 | 2002 | 56 | 48 | 38 |
101010 | 1120 | 42 | 36 | 2A |
11100 | 1001 | 28 | 24 | 1C |
1110 | 112 | 14 | 12 | E |
lab46:~/src/SEMESTER/unix/pwn1$
Multiple sans# options can be given, and will cancel out any present base (including those specified with a with# option). A sans# option for a non-existent base should be silently ignored.
INVALID ARGUMENTS AND EMPTY TABLES
Arguments that make no sense are silently dropped, as if they were never
given (no error messages, and the script runs on with whatever IS valid).
Here, by0, with1, sans99, and foo are all nonsense:
lab46:~/src/SEMESTER/unix/pwn1$ ./pwn1.sh 5 8 by0 with1 sans99 foo
base 2 | base 8 | base10 | base16 |
----------+----------+----------+----------+
101 | 5 | 5 | 5 |
110 | 6 | 6 | 6 |
111 | 7 | 7 | 7 |
1000 | 10 | 8 | 8 |
lab46:~/src/SEMESTER/unix/pwn1$
Order of the with# and sans# options does not matter: a sans# always wins. Below, base 3 is requested and then removed, so it never appears (and the step of 2 takes us through 5 and 7):
lab46:~/src/SEMESTER/unix/pwn1$ ./pwn1.sh 5 8 with3 by2 with3 sans3
base 2 | base 8 | base10 | base16 |
----------+----------+----------+----------+
101 | 5 | 5 | 5 |
111 | 7 | 7 | 7 |
lab46:~/src/SEMESTER/unix/pwn1$
And if every base is removed, there is nothing to display, so the script quietly exits (not even the header is printed, and the exit status is 0):
lab46:~/src/SEMESTER/unix/pwn1$ ./pwn1.sh sans2 sans8 sans10 sans16
lab46:~/src/SEMESTER/unix/pwn1$
Notice the next prompt immediately follows the command: nothing was displayed.
ONLINE HELP
Your script should also, when prompted, display usage information with the help option. The pwn1 help text covers the complete set of arguments:
lab46:~/src/SEMESTER/unix/pwn1$ ./pwn1.sh help
pwn1.sh - render a number table in the specified bases,
displaying from starting value to ending value.
behavior: by default, bases 2, 8, 10, and 16 will be
displayed, in a range of 0 to 15 (inclusive).
note: valid bases range from 2-16, and values should
not go negative nor exceed 255. If a starting
value but no ending value is given, assume an
ending value +15 away (or capped by 255).
usage: pwn1.sh [start#] [end#] [OPTION]...
options:
$1 - if a non-negative decimal value, override the
starting value (0)
$2 - if a non-negative decimal value, override the
ending value (15)
other options:
by# - iterate through values by # (default: 1)
with# - include base # in the list of bases to display
sans# - remove base # in the list of bases to display
help - display script usage and exit
lab46:~/src/SEMESTER/unix/pwn1$
(The complete online help is provided in the starter script.)
ARGUMENT RULES (CLARIFICATIONS)
To remove ambiguity, here is exactly how arguments are to be treated:
- help anywhere on the command line wins: display usage and exit (even if other arguments are present).
- Arguments may appear in any order relative to one another. The first whole number encountered is the starting value, the second is the ending value. Any further whole numbers are silently ignored.
- A "whole number" is an optional leading
-followed by one or more digits. Things like12.5,abc, or0x1Fare not whole numbers, and are silently dropped (as if never given). - Values below 0 become 0; values above 255 become 255 (this includes ridiculously long numbers). This applies to the start and the end value.
-
by# requires a whole number of at least 1.
by0,by,byx, andby-3are invalid and silently dropped. If by# is given more than once, the last valid one wins. The step is always a size: when counting backward, a step of 4 subtracts 4. The final value displayed is the last one reached without passing the ending value (so32 2 by4ends at 4). -
with# and sans# require a base from 2 to 16 (inclusive). Anything
else (
with1,with17,withx,with) is silently dropped. - The displayed bases are: (the defaults 2, 8, 10, 16, plus any valid
with#) minus any sans#, in ascending order, with no duplicates.
A sans# wins regardless of where it appears (
sans3 with3andwith3 sans3both result in no base 3). - If no bases remain, exit quietly with a status of 0, printing nothing at all (not even the header).
- If only a starting value is given (or none at all), the ending value is the starting value + 15, capped at 255.
- Nothing goes to STDERR, ever: this script has no error messages. The exit status is always 0.
SPECIFICATIONS
Evaluation will be based on correctness of values as well as on formatting/spacing.
You'll notice that everything lines up and is positioned similarly:
- each column exists within 10 characters of on-screen real estate:
- 8 characters for actual value display,
- with one space padding either side
- columns are separated with a
|symbol, appended to the right edge of the column (effectively making each column 11 characters wide).- note that the rightmost column is ended with this
|.
- note that the rightmost column is ended with this
- there is a heading/header at the top of the output table, and it uses a '+' to "connect" the horizontal and vertical lines being drawn
- The dashes and vertical bars set up an ASCII art-like table pattern that helps make the data more readable.
- The values are right justified with each column
- justification is essential. Everything should line up on its respective right margin.
- base headings are right justified; the word "base" is followed by the base number in a field 2 characters wide:
- you'll see "base 2" vs. "base16"; your script needs to accommodate this.
- You are to literally print out no more than 2 consecutive spaces at a time in your output statements (the help text is exempt from this rule). If you need more, use one of the formatting tools to generate spaces for you (printf(1) may be able to help you with this).
- You need to check your arguments to ensure they are present and valid. Some examples:
- starting value is a valid (whole) number
- if less than 0, or greater than 255, needs to be capped to whichever extreme it exceeds
- if -4, cap to 0
- if 300, cap to 255
- if less than 0, or greater than 255, needs to be capped to whichever extreme it exceeds
- ending value is a valid (whole) number
- if less than 0, or greater than 255, needs to be capped to whichever extreme it exceeds
- if -8, cap to 0
- if 420, cap to 255
- if less than 0, or greater than 255, needs to be capped to whichever extreme it exceeds
- any invalid arguments (nonsensical value in place of starting value, invalid base specification, etc.) should be silently dropped/ignored.
- starting value is a valid (whole) number
- default starting value is 0, default ending value is 15. If nothing else is validly provided, these are the values the script should run with.
- if starting and ending values are the same, the script will display just one line of number output (in addition to the header).
- if lacking any bases to display, silently exit (print nothing at all, not even the header, and exit with a status of 0)
- your script needs to commence with a proper shabang to bash; your script needs to end with an "exit 0" at the very end
- comments and indentation are required and necessary
- comments should explain how or why you are doing something
- indentation should be consistent throughout the script
- indentation is to be no less than 3 on-screen spaces (I recommend tabstops of 4).
- continuing with our shell scripting, your script will need to employ in a core/central way:
- variables
- command expansions
- regular expressions
- if statements
- loops
- your logic needs to:
- flow (one thing leads into the next, as best as possible)
- make sense within the given context
- avoid redundancy
- be understood by you (no grabbing snippets that seem to "work" from the internet)
- if you gain inspiration from some external resource, please cite it
- comments are a great way of demonstrating understanding (if you explain the why and how effectively, and it isn't in violation of other aspects, I'll know you are in control of things)
To be sure, I'll be checking to make sure your solution follows the spirit of what this project is about (that you implement functional, flowing logic utilizing the tools and concepts we've learned, in an application that helps demonstrate your comprehension). Don't try to weasel your way out of this or cut corners. This is an opportunity to further solidify your proficiency with everything.
SPIRIT OF PROJECT
The spirit of the project embodies many aspects we've been focusing on throughout the semester:
- recognizing patterns to employ effective solutions in problem solving
- utilizing concepts and tools covered
- demonstrating comprehension of concepts, tools, and problems
- employing concepts in knowledgeable and thoughtful manner
- following instructions
- implementing to specifications
- utilizing creativity
- being able to control solution via consistent, clear, and organized presentation
Basically: I want your solution to be the result of an honest, genuine brainstorming process where you have (on your own) figured out a path to solving the problem, you have dabbled and experimented and figured things out, and you can command the concepts and tools with a fluency enabling you to pull off such a feat. Your solution should demonstrate the real learning that took place and experience gained.
Cutting corners, avoiding work, skimping on functionality, cheating through getting others to do work for you or finding pre-packaged "answers" on the internet violates the spirit of the project, for they betray your ability to pull off the task on your own.
NOTE: some have instantiated controversy in the past by utilizing AI in a manner well beyond their abilities. In such cases, submitted work is not considered your own, and thereby inviting disciplinary action. Don't fall into that trap.
IDENTIFYING SHORTCOMINGS
I would also like it if you provided an inventory of what functionality is lacking or out of spec when you submit the project. The better you can describe your deviations from stated requirements, the more forgiving I may be during evaluation (versus trying to hide the shortcomings and hoping I do not discover them).
The more fluent you are in describing your shortcomings on accomplishing the project (ie "I didn't know how to do this" is far from fluent), the better I will be able to gauge your understanding on a particular aspect.
This can be in the form of comments in your script, or even a separate file submitted at time of submission (if a file, be sure to make mention of it in your script so I can be sure to look for it).
CONVERTING BETWEEN BASES
printf(1) can show a value in octal (%o) and hexadecimal (%x/%X),
but there is no format specifier for binary, nor for base 7 or base 12. The
bc(1) calculator, however, has an obase (output base) setting:
lab46:~$ echo "obase=12; 196" | bc
144
lab46:~$ echo "obase=2; 13" | bc
1101
lab46:~$ echo "obase=16; 196" | bc
C4
lab46:~$
(Note the digits above 9 come out as uppercase letters, just as the project
requires. The obase line must come before the number it should affect.)
You could also work out the conversion by hand with the repeated-division method: divide by the base, remember the remainder, repeat with the quotient until it reaches 0, and read the remainders in reverse. Either is fine, as long as you understand what you wrote.
A FEW MORE SCRIPTING TOOLS
Handling a changing list of bases, and a growing set of options, is easier with a few additional bash features. All of them are worth a visit to the bash(1) manual page.
arrays
An array holds a list of values under one name:
bases=(2 8 10 16)
bases+=(7) # append another element
echo "${bases[@]}" # all elements
echo "${#bases[@]}" # how many elements
for b in "${bases[@]}"; do
echo "base: ${b}"
done
Combine an array with other small tools to tidy it up; for instance, putting a list in order and discarding duplicates:
lab46:~$ bases=(2 8 10 16 7 8)
lab46:~$ printf "%s\n" "${bases[@]}" | sort -n | uniq
2
7
8
10
16
lab46:~$
functions
A function packages a repeated task so you write it (and debug it) once:
show_row() {
local value="$1" # arguments arrive as $1, $2, ...
printf "%s\n" "${value}"
}
show_row 42
Variables marked local exist only inside the function. Functions must be
defined before the line that calls them.
case statements
A case compares a value against a series of patterns:
case "${arg}" in
help) usage; exit 0 ;;
by[0-9]*) echo "looks like a step" ;;
*) ;; # anything else: silently ignored
esac
Be careful, though: those patterns are shell globs, not regular expressions.
by[0-9]* also accepts by5x, because * means "anything at all" here. When
exactness matters (and in this project it does), use a regular expression.
PATTERN MATCHING
In pwn0 you used a regular expression to recognize whole numbers. In pwn1, you
also have to recognize by#, with#, and sans# (and reject close-but-wrong
things like by, byx, by0, with17, wit8, and standby5).
When your pattern includes a capture group (parentheses), bash saves what it
matched in the BASH_REMATCH array:
lab46:~$ arg="by13"
lab46:~$ if [[ "${arg}" =~ ^by([0-9]+)$ ]]; then echo "step is ${BASH_REMATCH[1]}"; fi
step is 13
lab46:~$
Recognizing the shape of an argument is one task; deciding whether the number inside it is acceptable (a step of at least 1, a base from 2 to 16) is a separate task. Think about each as its own step.
SUBMISSION
By successfully performing this project, you should have a fully functioning script by the name of pwn1.sh, which is all you need to submit for project completion (no steps file, as your "steps" file IS the script you wrote).
This project continues your pwn0 work, so begin from your own pwn0.sh. A starter script is also available (it contains the identification block, the complete final help text, and notes on what is new):
$ cp /var/public/fall2026/UNIX/pwn1/pwn1.sh ~/src/SEMESTER/unix/pwn1/pwn1.sh
Your pwn1.sh must stand on its own (it may not depend on your pwn0.sh being present), and must satisfy everything in this document and in pwn0.
To submit this project to me using the submit tool, run the following command at your lab46 prompt:
$ submit unix pwn1 pwn1.sh
Submitting unix project "pwn1":
-> pwn1.sh(OK)
SUCCESSFULLY SUBMITTED
You should get some sort of confirmation indicating successful submission if all went according to plan. If not, check for typos and or locational mismatches.
What I'm looking for:
312:pwn1:final tally of results (312/312)
*:pwn1:pwn1.sh is a proper bash script: shabang, clean exit 0, parses, no hard-coded paths [13/13]
*:pwn1:pwn1.sh on help displays informative usage and exits [13/13]
*:pwn1:pwn1.sh formats output with printf width specifiers (no >2 literal spaces) [13/13]
*:pwn1:pwn1.sh accurately displays values in proper alignment [26/26]
*:pwn1:pwn1.sh effectively utilizes variables in operations [13/13]
*:pwn1:pwn1.sh effectively utilizes command expansions [13/13]
*:pwn1:pwn1.sh effectively utilizes selection statements [13/13]
*:pwn1:pwn1.sh effectively utilizes looping structures [13/13]
*:pwn1:pwn1.sh accurately displays values across combinations of options [26/26]
*:pwn1:pwn1.sh employs discrete single purpose utilities [13/13]
*:pwn1:pwn1.sh links tools through pipelines / command output streams [13/13]
*:pwn1:pwn1.sh uses regular expressions to validate numeric input [13/13]
*:pwn1:pwn1.sh uses pattern matching to parse by#/with#/sans# options [13/13]
*:pwn1:pwn1.sh range logic flexibly works forward and reverse [13/13]
*:pwn1:pwn1.sh iterates by # as appropriate in given scenarios [13/13]
*:pwn1:pwn1.sh includes (with#) and omits (sans#) bases as requested [13/13]
*:pwn1:pwn1.sh caps starting/ending values to the 0 to 255 bounds [13/13]
*:pwn1:pwn1.sh silently drops invalid arguments and still runs [13/13]
*:pwn1:pwn1.sh silently exits (status 0) when no bases remain [13/13]
*:pwn1:pwn1.sh comments explain how/why (header block, density, reasoning) [13/13]
*:pwn1:pwn1.sh logic is organized: consistent indentation (>=3), lines within 90 chars [13/13]
*:pwn1:pwn1.sh identifies shortcomings, deviations from specification [13/13]
Additionally:
- Solutions not abiding by the SPIRIT of the project (including hard-coded output) will be subject to a 25% overall deduction
- Solutions not utilizing descriptive why and how COMMENTS will be subject to a 25% overall deduction
- Solutions not utilizing INDENTATION to promote scope and clarity will be subject to a 25% overall deduction
- Solutions lacking ORGANIZATION or that are not easy to read (within 90 char width) are subject to a 25% overall deduction