-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
120 lines (111 loc) · 3.17 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
// Popcount is a program that returns the number of set bits, that is, bit whose
// value is 1, in a uint64 value, which is called its population count.
package main
import (
"bufio"
"fmt"
"os"
"popcount/algo"
"strconv"
"strings"
)
const (
colorReset = "\033[0m"
colorRed = "\033[31m"
colorGreen = "\033[32m"
)
var max, maxB int
func main() {
args := os.Args[1:]
if len(args) == 0 {
input := bufio.NewScanner(os.Stdin)
for input.Scan() {
inputs := strings.Split(input.Text(), " ")
if len(inputs) < 2 {
stop()
}
choice, _ := strconv.Atoi(inputs[0])
if choice > 3 || choice == 0 {
stop()
}
for i, arg := range inputs[1:] {
num, _ := strconv.Atoi(arg)
str := fmt.Sprintf("(%b)", num)
max, maxB = len(str), num
fmt.Print(countBits(i, choice, arg, inputs))
}
}
}
for _, arg := range args[1:] { // Set the number with the most bits (max) and the one with the most digits in base 10. (maxB)
num, _ := strconv.Atoi(arg)
str := fmt.Sprintf("(%b)", num)
if len(str) > max {
max = len(str)
}
if num > maxB {
maxB = num
}
}
choice, _ := strconv.Atoi(args[0])
if choice > 3 || choice == 0 {
stop()
}
for i, arg := range args[1:] {
fmt.Print(countBits(i, choice, arg, args))
}
}
// CountBits count set bits for each input.
func countBits(i, choice int, arg string, args []string) string {
num, err := strconv.Atoi(arg)
if err != nil {
str := fmt.Sprint(err)
strColored := " " + fmt.Sprint(string(colorRed), strings.TrimPrefix(str, "strconv.Atoi: parsing "), string(colorReset)) + "\n"
if i == 0 && len(args) > 2 { // Print algorithm sentence if there are other command-line arguments.
fmt.Printf("\nYou choose algorithm %v:\n\n", choice)
}
if i == 0 && len(args) == 2 { // Add new line if there is only one command-line argument (but badly formatted).
strColored = "\n" + strColored
}
fmt.Fprintf(os.Stderr, strColored)
return " "
}
if i == 0 { // Make algorithm sentence appears just once.
fmt.Printf("\nYou choose algorithm %v:\n\n", choice)
}
switch choice {
case 1:
res := fmt.Sprint(string(colorGreen), algo.Sum(uint64(num)), string(colorReset))
return formatOutput(res, num)
case 2:
res := fmt.Sprint(string(colorGreen), algo.Loop(uint64(num)), string(colorReset))
return formatOutput(res, num)
case 3:
res := fmt.Sprint(string(colorGreen), algo.Shift(uint64(num)), string(colorReset))
return formatOutput(res, num)
default:
stop()
return " "
}
}
// CountDig returns the number of digits if a integer.
func countDig(number int) int {
count := 0
for number != 0 {
number /= 10
count += 1
}
return count
}
// FormatOutput formats the output with color and padding.
func formatOutput(res string, num int) string {
arg := fmt.Sprint(string(colorGreen), num, string(colorReset))
byteStr := fmt.Sprintf("(%b)", num)
pad := max - len(byteStr) + countDig(maxB) - countDig(num) + 3
padStr := strings.Repeat(" ", pad) + byteStr
return fmt.Sprintf(" %v \t set bits in %v %s\n", res, arg, padStr)
}
// Stop function stop the program if the algotithm exeeds 3.
func stop() {
fmt.Println(string(colorRed), "\nPlease chose a number between 1 and 3 for algorithm", string(colorReset))
os.Exit(0)
}