Skip to content

Frihk/quadche

Repository files navigation

Quadchecker Program - Complete Documentation

Overview

The quadchecker program identifies which "quad" pattern function was used to create an ASCII art rectangle. It reads ASCII art from input and determines which of the 5 quad functions (quadA, quadB, quadC, quadD, quadE) produced that pattern.


How the Program Works

Simple Explanation

Think of it like a fingerprint detector:

  1. Someone gives you a piece of ASCII art (like a box made with characters)
  2. The program knows 5 different ways to make boxes (the 5 quad functions)
  3. It generates all 5 patterns with the same size as the input
  4. It compares the input with each pattern to find which one(s) match
  5. It tells you which pattern(s) matched and the dimensions

Step-by-Step Process

  1. Read Input: The program reads ASCII art from stdin (what you pipe into it)
  2. Remove Newline: It cleans up the final newline character
  3. Extract Dimensions: It figures out how wide and tall the rectangle is
  4. Validate: It checks that all lines are the same width (a valid rectangle)
  5. Generate Patterns: It creates all 5 quad patterns with the same dimensions
  6. Compare: It compares the input with each generated pattern
  7. Sort Results: It lists all matches alphabetically
  8. Output: It prints the results in the format: [quadX] [width] [height]

Understanding the 5 Quad Functions

Each quad function creates a rectangle border using different characters.

quadA - Circles and Lines

Uses: o (corners), - (top/bottom), | (left/right)

Example (5×3):

o---o
|   |
o---o

How it works:

  • Corners get o
  • Top and bottom edges get -
  • Left and right edges get |
  • Inside gets space

quadB - Diagonals and Asterisks

Uses: /, \ (corners), * (other edges)

Example (5×3):

/---\
*   *
\---/

How it works:

  • Top-left and bottom-right corners get /
  • Top-right and bottom-left corners get \
  • All other edges get *
  • Inside gets space

quadC - Letters (A at top, C at bottom)

Uses: A (top corners), C (bottom corners), B (other edges)

Example (5×3):

AAAAA
BBBBB
CCCCC

How it works:

  • Top corners get A
  • Bottom corners get C
  • All other edges get B
  • Inside gets space

quadD - Letters (A on left, C on right)

Uses: A (top-left and bottom-left), C (top-right and bottom-right), B (other edges)

Example (5×3):

ACCCA
BBBBB
ACCCA

How it works:

  • Top-left and bottom-left corners get A
  • Top-right and bottom-right corners get C
  • All other edges get B
  • Inside gets space

quadE - Letters (A diagonal, C diagonal)

Uses: A (top-left and bottom-right), C (top-right and bottom-left), B (other edges)

Example (5×3):

ACCCA
BBBBB
CAAAC

How it works:

  • Top-left and bottom-right corners get A
  • Top-right and bottom-left corners get C
  • All other edges get B
  • Inside gets space

Creating the Test Executable Files

The test files (quadA, quadB, quadC, quadD, quadE) are executable programs that generate the quad patterns. You only need to create them once to test the checker.

Why Do We Need These Files?

The quadchecker program needs a way to generate test input. Instead of typing out rectangles manually, we have these small programs that do it for us. They take two numbers (width and height) and output the corresponding quad pattern.

Important Note About Function Names

In the test files, the function names are different from the main.go file:

  • In main.go: functions are named quadA, quadB, quadC, quadD, quadE (lowercase 'quad')
  • In test files: functions are named genA, genB, genC, genD, genE (using 'gen' prefix)

Why the difference?

The main.go functions (quadA, quadB, etc.) are the "checker" functions - they generate patterns to compare against the input. They must have the exact same logic as the quad functions.

The test files use genA, genB, etc. because:

  1. They're separate executable programs (not part of the main program)
  2. Using different names makes it clear these are generator functions
  3. When we build them into executables (quadA, quadB, etc.), the executable name is what matters, not the function name
  4. It avoids confusion - the executable is named quadA (which comes from the main package), and it has a function genA inside it

How to Create quadA (Step by Step)

Step 1: Create a file named quadA.go with this code:

package main

import (
	"fmt"
	"os"
	"strconv"
)

// genA generates the quadA pattern
func genA(w, h int) string {
	if w <= 0 || h <= 0 {
		return ""
	}
	b := make([]byte, 0, (w+1)*h)
	for r := 0; r < h; r++ {
		for c := 0; c < w; c++ {
			switch {
			case r == 0 && c == 0, r == 0 && c == w-1, r == h-1 && c == 0, r == h-1 && c == w-1:
				b = append(b, 'o')
			case r == 0 || r == h-1:
				b = append(b, '-')
			case c == 0 || c == w-1:
				b = append(b, '|')
			default:
				b = append(b, ' ')
			}
		}
		b = append(b, '\n')
	}
	return string(b)
}

func main() {
	if len(os.Args) < 3 {
		return
	}
	w, _ := strconv.Atoi(os.Args[1])
	h, _ := strconv.Atoi(os.Args[2])
	fmt.Print(genA(w, h))
}

Step 2: Compile it into an executable:

go build -o quadA quadA.go

Step 3: Test it:

./quadA 5 3

You should see:

o---o
|   |
o---o

How to Create All Test Files (Quick Method)

Run these commands in the /home/mightpush/test-go/quadchecker directory:

Create quadB

cat > quadB.go << 'EOF'
package main

import (
	"fmt"
	"os"
	"strconv"
)

func genB(w, h int) string {
	if w <= 0 || h <= 0 {
		return ""
	}
	b := make([]byte, 0, (w+1)*h)
	for r := 0; r < h; r++ {
		for c := 0; c < w; c++ {
			switch {
			case r == 0 && c == 0 || r == h-1 && c == w-1:
				b = append(b, '/')
			case r == 0 && c == w-1 || r == h-1 && c == 0:
				b = append(b, '\\')
			case r == 0 || r == h-1 || c == 0 || c == w-1:
				b = append(b, '*')
			default:
				b = append(b, ' ')
			}
		}
		b = append(b, '\n')
	}
	return string(b)
}

func main() {
	if len(os.Args) < 3 {
		return
	}
	w, _ := strconv.Atoi(os.Args[1])
	h, _ := strconv.Atoi(os.Args[2])
	fmt.Print(genB(w, h))
}
EOF
go build -o quadB quadB.go

Create quadC

cat > quadC.go << 'EOF'
package main

import (
	"fmt"
	"os"
	"strconv"
)

func genC(w, h int) string {
	if w <= 0 || h <= 0 {
		return ""
	}
	b := make([]byte, 0, (w+1)*h)
	for r := 0; r < h; r++ {
		for c := 0; c < w; c++ {
			switch {
			case r == 0 && c == 0 || r == 0 && c == w-1:
				b = append(b, 'A')
			case r == h-1 && c == 0 || r == h-1 && c == w-1:
				b = append(b, 'C')
			case r == 0 || r == h-1 || c == 0 || c == w-1:
				b = append(b, 'B')
			default:
				b = append(b, ' ')
			}
		}
		b = append(b, '\n')
	}
	return string(b)
}

func main() {
	if len(os.Args) < 3 {
		return
	}
	w, _ := strconv.Atoi(os.Args[1])
	h, _ := strconv.Atoi(os.Args[2])
	fmt.Print(genC(w, h))
}
EOF
go build -o quadC quadC.go

Create quadD

cat > quadD.go << 'EOF'
package main

import (
	"fmt"
	"os"
	"strconv"
)

func genD(w, h int) string {
	if w <= 0 || h <= 0 {
		return ""
	}
	b := make([]byte, 0, (w+1)*h)
	for r := 0; r < h; r++ {
		for c := 0; c < w; c++ {
			switch {
			case r == 0 && c == 0 || r == h-1 && c == 0:
				b = append(b, 'A')
			case r == 0 && c == w-1 || r == h-1 && c == w-1:
				b = append(b, 'C')
			case r == 0 || r == h-1 || c == 0 || c == w-1:
				b = append(b, 'B')
			default:
				b = append(b, ' ')
			}
		}
		b = append(b, '\n')
	}
	return string(b)
}

func main() {
	if len(os.Args) < 3 {
		return
	}
	w, _ := strconv.Atoi(os.Args[1])
	h, _ := strconv.Atoi(os.Args[2])
	fmt.Print(genD(w, h))
}
EOF
go build -o quadD quadD.go

Create quadE

cat > quadE.go << 'EOF'
package main

import (
	"fmt"
	"os"
	"strconv"
)

func genE(w, h int) string {
	if w <= 0 || h <= 0 {
		return ""
	}
	b := make([]byte, 0, (w+1)*h)
	for r := 0; r < h; r++ {
		for c := 0; c < w; c++ {
			switch {
			case r == 0 && c == 0 || r == h-1 && c == w-1:
				b = append(b, 'A')
			case r == 0 && c == w-1 || r == h-1 && c == 0:
				b = append(b, 'C')
			case r == 0 || r == h-1 || c == 0 || c == w-1:
				b = append(b, 'B')
			default:
				b = append(b, ' ')
			}
		}
		b = append(b, '\n')
	}
	return string(b)
}

func main() {
	if len(os.Args) < 3 {
		return
	}
	w, _ := strconv.Atoi(os.Args[1])
	h, _ := strconv.Atoi(os.Args[2])
	fmt.Print(genE(w, h))
}
EOF
go build -o quadE quadE.go

Testing the Program

Build the checker first

go build -o quadchecker main.go

Test 1: Single match

./quadA 3 3 | go run main.go

Expected output:

[quadA] [3] [3]

Test 2: Multiple matches

./quadC 1 1 | go run main.go

Expected output:

[quadC] [1] [1] || [quadD] [1] [1] || [quadE] [1] [1]

Test 3: Invalid input

echo "0 0" | go run main.go

Expected output:

Not a quad function

Test 4: Malformed input

echo -n "o--o"$'\n'"|"$'\n'"o" | go run main.go

Expected output:

Not a quad function

Key Points to Remember

  1. The main.go has the checker logic - It contains quadA, quadB, etc. functions that generate patterns for comparison

  2. The executable files (quadA, quadB, etc.) are generators - They contain genA, genB, etc. functions that are used for testing

  3. Function naming matters - Use gen* in executable files to avoid confusion with the checker functions

  4. The logic must match - The quadA function in main.go must produce the exact same output as the genA function in quadA.go, otherwise tests will fail

  5. You can delete the .go files - After building the executables, you can safely delete the source files (quadA.go, quadB.go, etc.). The compiled executables don't need them

  6. Two different packages - main.go is one program, while quadA.go, quadB.go, etc. are separate programs. They both use package main because each is its own executable


Summary

  • quadchecker (main.go): Reads input and identifies which quad pattern it matches
  • quadA, quadB, quadC, quadD, quadE: Generate test patterns for the checker
  • Function names differ: checker uses quadA, generators use genA
  • All outputs must match: The logic in both places must produce identical rectangles
  • Fully commented code: main.go includes detailed comments explaining each step

Good luck with your testing!

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors