Можно ли переписать этот код покрасивее?
Решал задачу из курса на Stepik:
По данному трехзначному числу определите, все ли его цифры различны.
Формат входных данных
На вход подается одно натуральное трехзначное число.
Формат выходных данных
Выведите "YES", если все цифры числа различны, в противном случае - "NO".
Я написал такой код (полностью рабочий, все правильно решает):
package main
import "fmt"
func main() {
var num, a, b, c int
fmt.Scan(&num)
a = num % 10
b = num % 100 / 10
c = num % 1000 / 100
if a == b || a == c || b == c {
fmt.Println("NO")
} else {
fmt.Println("YES")
}
}
Но он получился не очень красивый (a == b || a == c || b == c), даже немного запутанный.
Как это можно сделать покрасивее? Я думаю можно что-нибудь с массивами сделать, но я пока ещё новичок в GoLang, и поэтому прошу помощи.
Ответы (4 шт):
Могу предложить идеологически другой вариант - читаем строку, преобразуем в массив чисел, добавляем эти числа в мапу в качестве ключа и если размер мапы равен размеру массива (в вашем случае 3), то все числа уникальные.
func main() {
var num string
fmt.Scan(&num)
arr := strings.Split(num, "")
m := map[string]struct{}{}
for _, v := range arr {
m[v] = struct{}{}
}
if len(m) != len(arr) {
fmt.Println("NO")
} else {
fmt.Println("YES")
}
}
UPD небольшая оптимизация по совету @Кирилл Новгородцев: перед добавлением ключа в мапу идёт проверка на наличие ключа - если таковой имеется то фиксируем что дубликат существует и прерываем цикл
func main() {
var num string
fmt.Scan(&num)
m := map[string]struct{}{}
result := "YES"
for _, v := range strings.Split(num, "") {
if _, ok := m[v]; ok {
result = "NO"
break;
}
m[v] = struct{}{}
}
fmt.Println(result)
}
Вариант без бессмысленного использования строк, хештаблиц или динамических массивов. Посимвольное чтение с окончанием работы при нахождении первого повтора.
package main
import "fmt"
func main() {
var seen [10] bool
for {
var char rune
fmt.Scanf("%c", &char)
if char < '0' || '9' < char {
fmt.Println("YES")
break
}
var index = int(char - '0')
if seen[index] {
fmt.Println("NO")
break
}
seen[index] = true
}
}
Я нашел, наверное самое лаконичное решение:
package main
import "fmt"
func main() {
var num int
var seen [10]bool
for {
_, err := fmt.Scanf("%1d", &num)
if err != nil {
fmt.Println("YES")
break
} else if seen[num] {
fmt.Println("NO")
break
}
seen[num] = true
}
}
полирнем ;)
- в предположении, что число положительное, не содержит лидирующих нулей и помещается в int
package main
import "fmt"
func allDigitsDifferent(num int) bool {
var seen int
for num > 0 {
dig := 1 << (num % 10)
if seen & dig != 0 {
return false
}
seen |= dig
num /= 10
}
return true
}
func main() {
var num int
fmt.Scan(&num)
if allDigitsDifferent(num) {
fmt.Println("YES")
} else {
fmt.Println("NO")
}
}