Решение ребуса: гол * гол = футбол
1 минут
Попросили меня решить ребус вида гол * гол = футбол
. Написал решение на C. Зачем это здесь? Просто я давно ничего не постил в блог, надо немного освежить содержимое. Ну и это может быть полезным для тех, кто ещё только изучает C :). Код прокомментирован на русском языке.
Обновлено 20.09.2025: исправлено решение на C и добавлено решение на Rust.
Решение на C:
/*
Решение маски abc * abc = defbc (ребус: гол * гол = футбол)
*/
#include <stdio.h>
#include <math.h>
#define SIZE_A 3
#define SIZE_B 6
int main()
{
int num = 0, i, j, n, a[SIZE_A], b[SIZE_B];
for (n = 100; n <= 999; n++) {
num = n;
// записываем цифры числа num в массив
a[0] = num % 10;
a[1] = num / 10 % 10;
a[2] = num / 100 % 10;
// проверяем эквивалентность цифр в числе a
if (a[0] == a[1] || a[0] == a[2] || a[1] == a[2]) {
continue;
}
num *= num;
if (num > 999999) {
continue;
}
// записываем цифры числа num в массив
b[0] = num % 10;
b[1] = num / 10 % 10;
// проверяем идентичность двух последних цифр в числе
if (b[0] != a[0] || b[1] != a[1]) {
continue;
}
b[2] = num / 100 % 10;
b[3] = num / 1000 % 10;
b[4] = num / 10000 % 10;
b[5] = num / 100000 % 10;
// проверяем эквивалентность цифр в числе b
for (i = 0; i < SIZE_B; i++) {
for (j = i+1; j < SIZE_B; j++) {
// если нашлись какие-нибудь одинаковые значения, то прерываем цикл
if (b[i] == b[j]) {
num = 0;
break;
}
}
}
// проверяем эквивалентность цифр в числах a и b
for (i = 0; i < SIZE_A; i++) {
for (j = 0; j < SIZE_B; j++) {
// игнорируем значения, которые должны быть равными
if ((i == 0 && j == 0) || (i == 1 && j == 1)) {
continue;
}
// если нашлись какие-нибудь одинаковые значения, то прерываем цикл
if (a[i] == b[j]) {
num = 0;
break;
}
}
}
// вывод результата
if (num != 0) {
num = sqrt(num);
printf("%d * %d = %d\n", num, num, num*num);
}
}
return 0;
}
Решение на Rust:
use std::collections::HashSet;
const VALUE_DIGITS: u32 = 3;
const VALUE_FROM: u32 = (10_u32).pow(VALUE_DIGITS - 1);
const VALUE_TO: u32 = (10_u32).pow(VALUE_DIGITS);
const RESULT_DIGITS: u32 = 6;
const RESULT_FROM: u32 = (10_u32).pow(RESULT_DIGITS - 1);
const RESULT_TO: u32 = (10_u32).pow(RESULT_DIGITS);
fn main() {
for value in VALUE_FROM..VALUE_TO {
if is_valid_gol_value(value) {
println!("{} * {} = {}", value, value, value * value);
}
}
}
fn is_valid_gol_value(value: u32) -> bool {
let result = value * value;
if !(RESULT_FROM..RESULT_TO).contains(&result) {
return false;
}
let value_arr = make_digits_vec(value, VALUE_DIGITS);
if !is_only_uniq_values(&value_arr) {
return false;
}
let result_arr = make_digits_vec(result, RESULT_DIGITS);
if !is_only_uniq_values(&result_arr) {
return false;
}
let value_index = value_arr.len() - 2;
let result_index = result_arr.len() - 2;
if !value_arr[value_index..].eq(&result_arr[result_index..]) {
return false;
}
value_arr[..value_index]
.iter()
.any(|v| !result_arr[..result_index].contains(v))
}
fn make_digits_vec(value: u32, digits: u32) -> Vec<u32> {
(0..digits)
.rev()
.map(|v| value / 10_u32.pow(v) % 10)
.collect()
}
fn is_only_uniq_values(arr: &[u32]) -> bool {
arr.iter().collect::<HashSet<_>>().len() == arr.len()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn valid_values() {
assert_eq!(is_valid_gol_value(425), true);
}
#[test]
fn invalid_values() {
let mut errors = 0;
for i in 0..9999 {
if i != 425 && is_valid_gol_value(i) {
println!("error value: {}", i);
errors += 1;
}
}
assert_eq!(errors, 0);
}
}