I have mapped user input with 2d ascii letters and now I am trying to print out ascii letters below horizontally, so they could be printed side by side not top down as they are right now. Letter height is 8 lines and width varies. I run the code go run . "hello" Could really appriciate some help. I have tried to loop over the Table, but no success and haveb't been able to figure out yet how to print letters side by side.
_
| |
| |__
| _ \
| | | |
|_| |_|
___
/ _ \
| __/
\___|
_
| |
| |
| |
| |
|_|
_
| |
| |
| |
| |
|_|
___
/ _ \
| (_) |
\___/
I use struct for mapping and storying data on that format below:
{h 104 [[ ] [_] [ ] [ ] [ ] [ ] [ ] [ ]] []}
{h 104 [[|] [ ] [|] [ ] [ ] [ ] [ ] [ ]] []}
{h 104 [[|] [ ] [|] [_] [_] [ ] [ ] [ ]] []}
{h 104 [[|] [ ] [ ] [_] [ ] [\] [ ] [ ]] []}
{h 104 [[|] [ ] [|] [ ] [|] [ ] [|] [ ]] []}
{h 104 [[|] [_] [|] [ ] [|] [_] [|] [ ]] []}
{h 104 [[ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ]] []}
{h 104 [[ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ]] []}
{e 101 [[ ] [ ] [ ] [ ] [ ] [ ] [ ]] []}
{e 101 [[ ] [ ] [ ] [ ] [ ] [ ] [ ]] []}
{e 101 [[ ] [ ] [_] [_] [_] [ ] [ ]] []}
{e 101 [[ ] [/] [ ] [_] [ ] [\] [ ]] []}
{e 101 [[|] [ ] [ ] [_] [_] [/] [ ]] []}
{e 101 [[ ] [\] [_] [_] [_] [|] [ ]] []}
{e 101 [[ ] [ ] [ ] [ ] [ ] [ ] [ ]] []}
{e 101 [[ ] [ ] [ ] [ ] [ ] [ ] [ ]] []}
{l 108 [[ ] [_] [ ] [ ]] []}
{l 108 [[|] [ ] [|] [ ]] []}
{l 108 [[|] [ ] [|] [ ]] []}
{l 108 [[|] [ ] [|] [ ]] []}
{l 108 [[|] [ ] [|] [ ]] []}
{l 108 [[|] [_] [|] [ ]] []}
{l 108 [[ ] [ ] [ ] [ ]] []}
{l 108 [[ ] [ ] [ ] [ ]] []}
{l 108 [[ ] [_] [ ] [ ]] []}
{l 108 [[|] [ ] [|] [ ]] []}
{l 108 [[|] [ ] [|] [ ]] []}
{l 108 [[|] [ ] [|] [ ]] []}
{l 108 [[|] [ ] [|] [ ]] []}
{l 108 [[|] [_] [|] [ ]] []}
{l 108 [[ ] [ ] [ ] [ ]] []}
{l 108 [[ ] [ ] [ ] [ ]] []}
{o 111 [[ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ]] []}
{o 111 [[ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ]] []}
{o 111 [[ ] [ ] [_] [_] [_] [ ] [ ] [ ]] []}
{o 111 [[ ] [/] [ ] [_] [ ] [\] [ ] [ ]] []}
{o 111 [[|] [ ] [(] [_] [)] [ ] [|] [ ]] []}
{o 111 [[ ] [\] [_] [_] [_] [/] [ ] [ ]] []}
{o 111 [[ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ]] []}
{o 111 [[ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ]] []}
My code ascii.go:
import (
"fmt"
"os"
"strings"
)
type letter struct {
Letter string
Ascii int
Table [][]string
Color []string
}
func mapFont(font string) ([]letter, error) {
readFile, err := os.ReadFile(font)
if err != nil {
return nil, fmt.Errorf("could not read the content in the file: %v", err)
}
slice := strings.Split(string(readFile), "\n")
letters := make([]letter, 0)
index := 31
for _, row := range slice {
if row == "" {
index++
continue
}
grid := make([][]string, 0)
for _, char := range row {
grid = append(grid, []string{string(char)})
}
letters = append(letters, letter{
Letter: string(index),
Ascii: index,
Table: grid,
})
}
return letters, nil
}
func mapInput(input string, letters []letter) ([]letter, error) {
lines := strings.Split(input, "\\n")
output := make([]letter, 0)
for _, line := range lines {
characters := []rune(line)
if line != "" {
for _, ch := range characters {
if ch >= 32 && ch <= 126 {
for _, v := range letters {
if rune(v.Ascii) == ch {
output = append(output, v)
}
}
} else {
return nil, fmt.Errorf("input includes non ascii character(s), please use ascii character(s)")
}
}
} else {
output = append(output, letter{})
}
}
return output, nil
}
func printLettersSideBySide(mapping []letter) {
output := ""
for i := 0; i < len(mapping); i++ {
for j := 0; j < len(mapping[i].Table); j++ {
output = output + strings.Join(mapping[i].Table[j], "")
}
output = output + "\n"
}
fmt.Println(output)
}
main.go
package main
import (
"fmt"
)
func main() {
args := os.Args
banners := "banner/standard.txt"
str := args[1]
letter, _ := mapFont(banners)
mapping, _ := mapInput(str, letter)
printLettersSideBySide(mapping)
for _, item := range mapping {
fmt.Println(item)
}
}
Leaving answer to others who may need it:
Was able to solve it by making data structure for Table in type letter simpler. Replaced [][]string with []string in and made changes in mapFont function where I used that struct. Then I added new function for printing letters horizontally.
ascii.go
import (
"fmt"
"os"
"strings"
)
type letter struct {
Letter string
Ascii int
Table []string
}
func mapFont(font string) ([]letter, error) {
readFile, err := os.ReadFile(font)
if err != nil {
return nil, fmt.Errorf("could not read the content in the file: %v", err)
}
slice := strings.Split(string(readFile), "\n")
letters := make([]letter, 0)
index := 31
for _, row := range slice {
if row == "" {
index++
continue
}
grid := make([]string, 0)
for _, char := range row {
grid = append(grid, string(char))
}
letters = append(letters, letter{
Letter: string(index),
Ascii: index,
Table: grid,
})
}
return letters, nil
}
func mapInput(input string, letters []letter) ([]letter, error) {
lines := strings.Split(input, "\\n")
output := make([]letter, 0)
for _, line := range lines {
characters := []rune(line)
if line != "" {
for _, ch := range characters {
if ch >= 32 && ch <= 126 {
for _, v := range letters {
if rune(v.Ascii) == ch {
output = append(output, v)
}
}
} else {
return nil, fmt.Errorf("input includes non ascii character(s), please use ascii character(s)")
}
}
} else {
output = append(output, letter{})
}
}
return output, nil
}
func printInput(str string, letter []letter) []string {
var pixelRows []string
for row := 0; row < 8; row++ {
pixelRow := ""
for letterIndex := 0; letterIndex < len(str); letterIndex++ {
character, _ := mapInput(string(str[letterIndex]), letter)
for column := 0; column < len(character[row].Table); column++
pixelRow = pixelRow + character[row].Table[column]
}
}
pixelRows = append(pixelRows, pixelRow)
}
return pixelRows
}
main.go
package main
import (
"fmt"
"os"
)
func main() {
args := os.Args
banners := "banner/standard.txt"
str := args[1]
letter, _ := mapFont(banners)
sentence, _ := mapInput(str, letter)
output := printInput(str, sentence)
for _, v := range output {
fmt.Println(v)
}
}
Output:
❯ go run . "hello"
_ _ _
| | | | | |
| |__ ___ | | | | ___
| _ \ / _ \ | | | | / _ \
| | | | | __/ | | | | | (_) |
|_| |_| \___| |_| |_| \___/
Related
The following code is displaying a Progress Bar on an HTML page. It runs fine but takes up far to many lines of code.
QUESTION:
- How would I go about transforming this into a for or while loop, replicating its functionality?
if [ $per_usage -ge 1 ] && [ $per_usage -le 10 ]
then
indg="|"
indb=""
indr=""
elif [ $per_usage -gt 10 ] && [ $per_usage -le 20 ]
then
indg="||"
indb=""
indr=""
elif [ $per_usage -gt 20 ] && [ $per_usage -le 30 ]
then
indg="|||"
indb=""
indr=""
elif [ $per_usage -gt 30 ] && [ $per_usage -le 40 ]
then
indg="||||"
indb=""
indr=""
elif [ $per_usage -gt 40 ] && [ $per_usage -le 50 ]
then
indg="|||||"
indb=""
indr=""
elif [ $per_usage -gt 50 ] && [ $per_usage -le 60 ]
then
indg="|||||"
indb="|"
indr=""
elif [ $per_usage -gt 60 ] && [ $per_usage -le 70 ]
then
indg="|||||"
indb="||"
indr=""
elif [ $per_usage -gt 70 ] && [ $per_usage -le 80 ]
then
indg="|||||"
indb="|||"
indr=""
elif [ $per_usage -gt 80 ] && [ $per_usage -le 90 ]
then
indg="|||||"
indb="||"
indr="||"
elif [ $per_usage -gt 90 ]
then
indg=""
indb=""
indr="||||||||||"
else
indg=""
indb=""
indr=""
fi
For example my output is like if per_usage value is 41
41 % |||||
Thank you in advance.
This sort of thing can be looped pretty easily:
#!/bin/bash
get_string () {
per_usage="$1"
if [ "$per_usage" -le 100 ] && [ "$per_usage" -ge 0 ]; then
echo -en "${per_usage}%\t"
bars=$(($per_usage / 10 + 1))
printf "%0.s|" $(seq 1 $bars)
echo
fi
}
i=0
while [ "$i" -le 100 ]; do
string=$(get_string "$i")
echo "$string"
let i++
done
In this example, the get_string function can be used to generate a string based on an input number. For instance, get_string 41 will print 41% |||||. In the little while loop below, the string for 0 - 100 is stored in the $string variable and printed.
bars stores the number of bars to print. Just one bar per 10%. Then printf and seq are used to print a | bars number of times.
Hopefully with this, you'll be on the right track to cleaning up your code.
I am trying to run a shell script in OS X Terminal. The program terminates whenever you enter an m or a.
Problem is, I can't get the OR statement working.
#!/bin/sh
read File
while [ "$File" != "m" ] || [ "$File" != "a" ]
do
read File
done
When I just do
while [ "$File" != "m" ]
It works perfectly fine. I have tried multiple methods, such as
while test $File != "m" || test $File != "a"
while test $File != "m" -o test $File != "a"
while [ $File != "m" -o $File != "a" ]
None of them seem to work.
The above code I posted does not stop looping when the user inputs an "m" or an
I suggest to replace
while [ "$File" != "m" ] || [ "$File" != "a" ]
by
while [ "$File" != "m" ] && [ "$File" != "a" ]
or
until [ "$File" = "m" ] || [ "$File" = "a" ]
or with a regex (bash):
while [[ ! $File =~ m|a ]]
See from bash: help until
I am trying to write a script but it is giving the above error
if [ [ [ "$1" != "abc" ] && [ "$1" != "def" ] ] || [ [ "$2" != "1" ] && [ "$2" != "0" ] ] ];
then
echo "Hello World"
fi
Be careful with && and ||. You can simplify it to this in BASH:
if [[ "$1" != "abc" && "$1" != "def" ]] || [[ "$2" != "1" && "$2" != "0" ]];
then
echo "Hello World"
fi
I've been trying to make this thing work for a couple of hours but I can't get it to work :
if [ "$P" = "SFTP" -a "$PORT" != "22" ] || [ "$P" = "FTPS" && [ "$PORT" != "990" -a "$PORT" != "21" ] ] ; then
Can someone help me ? I know that multiple conditions can be written like this :
if [ "$P" = "SFTP" ] && [ "$PORT" != "22" ]; then
but how can I imbricate theses conditions like in my first example?
You can't nest expressions in single brackets. It should be written like this:
if [ "$P" = "SFTP" -a "$PORT" != "22" ] || [ "$P" = "FTPS" -a "$PORT" != "990" -a "$PORT" != "21" ] ; then
This can be written as a single expressions as:
if [ \( "$P" = "SFTP" -a "$PORT" != "22" \) -o \( "$P" = "FTPS" -a "$PORT" != "990" -a "$PORT" != "21" \) ] ; then
although is is not fully compatible with all shells.
Since you are using bash, you can use double brackets to make the command more readable:
if [[ ( $P = "SFTP" && $PORT != "22" ) || ( $P = "FTPS" && $PORT != "990" && $PORT != "21" ) ]] ; then
Can any one tell what wrong with this script ?. Because I am getting the error like
./timer: line 9: [13: command not found
./timer: line 12: [13: command not found
My script look like
#!/bin/bash
while :
do
HOUR=$(date +%H)
MINUTE=$(date +%M)
SECOND=$(date +%S)
if [$HOUR == 13] && [$MINUTE == 12] && [$SECOND == 1]
then ./binary
elif [$HOUR == 18] && [$MINUTE == 30] && [$SECOND == 1]
then ./binary
fi
done
put a space between the [ ... ]
Example:
if [$HOUR == 13] && [$MINUTE == 12] && [$SECOND == 1]
Should become
if [ $HOUR == 13 ] && [ $MINUTE == 12 ] && [ $SECOND == 1 ]
I think you must use "${VARIABLE}" and respect spaces for square brackets
This would give :
if [ "${HOUR}" == 13 ] && [ "${HOUR}" == 12 ] && [ "${HOUR}" == 1 ]
Hope that helps !
the test operators in bash need to have a space by the opening and closing bracket, try
[ $HOUR == 13 ] && [ $MINUTE == 12 ] && [ $SECOND == 1 ]
and
[ $HOUR == 18 ] && [ $MINUTE == 30 ] && [ $SECOND == 1 ]
here is a link that you might find useful
http://tldp.org/LDP/abs/html/testconstructs.html
Several things:
You have to put a space after [ and before ].
It's a good practice to protect your variables using double quotes.
You have to use the -eq operator to compare numeric values (see Bash conditional operators).
Like so:
if [ "$HOUR" -eq 13] && [ "$MINUTE" -eq 12 ] && [ "$SECOND" -eq 1 ]
elif [ "$HOUR" -eq 18 ] && [ "$MINUTE" -eq 30 ] && [ "$SECOND" -eq 1 ]