喊7的次数重排

题目描述

喊7是一个传统的聚会游戏, N个人围成一圈, 按顺时针从1到N编号.

编号为1的人从1开始喊数, 下一个人喊的数字为上一个人的数字加1, 但是当将要喊出来的数字是7的倍数或者数字本身含有7的话, 不能把这个数字直接喊出来, 而是要喊"过".

假定玩这个游戏的N个人都没有失误地在正确的时机喊了"过", 当喊到数字K时, 可以统计每个人喊"过"的次数.

现给定一个长度为N的数组, 存储了打乱顺序的每个人喊"过"的次数, 请把它还原成正确的顺序, 即数组的第i个元素存储编号i的人喊" 过"的次数.

输入描述

输入为一行, 为空格分隔的喊"过"的次数, 注意K并不提供, K不超过200, 而数字的个数即为N.

输出描述

输出为一行, 为顺序正确的喊"过"的次数, 也由空格分隔.

示例1

输入:

0 1 0

输出:

1 0 0

说明: 一共只有一次喊"过", 那只会发生在需要喊7时, 按顺序, 编号为1的人会遇到7, 故输出1 0 0.

示例2

输入:

0 1 2 0 0

输出:

0 2 0 1 0

说明: 一共有三次喊"过", 发生在 7 14 17, 按顺序, 编号为2的人会遇到 7 17, 编号为4的人会遇到14, 故输出 0 2 0 1 0.

题解

Python


def main():
    # 读取输入
    # 确定有人数 n
    # 确定总共喊了多少声
    # 基于此, 就可以确定喊的顺序
    pass_list = list(map(int, input().split()))
    # 得到人数
    num_people = len(pass_list)
    assert 0 < num_people
    # 喊过的总次数
    total_passes = sum(pass_list)

    # 喊过的条件是:
    # 1. 当前数字是7的倍数
    # 2. 当前数字中包含7

    # 每个人真正喊过的次数
    real_pass_list = [0] * num_people

    # 当前的喊的数字 k, 注意数字是从1开始
    current_num = 1
    # 当前喊数的人在队列中的位置, 从0开始计数
    current_person = 0

    # 一直循环, 直到喊过的次数用完了
    while total_passes > 0:
        if current_num % 7 == 0 or "7" in str(current_num):
            # 这个人要喊过
            real_pass_list[current_person] += 1
            total_passes -= 1
        current_num += 1
        current_person = (current_person + 1) % num_people

    # 打印结果
    print(" ".join(map(str, real_pass_list)))

if __name__ == "__main__":
    main()

Rust

use std::io::{stdin, BufRead};

fn number_digits_contains(mut num: u32, digit: u8) -> bool {
    while num > 0 {
        let d = (num % 10) as u8;
        if d == digit {
            return true;
        }
        num /= 10;
    }
    false
}

fn solution() {
    // 读取输入
    // 确定有人数 n
    // 确定总共喊了多少声
    // 基于此, 就可以确定喊的顺序
    let mut line = String::new();
    let ret = stdin().lock().read_line(&mut line);
    assert!(ret.is_ok());
    let pass_list: Vec<u32> = line
        .trim()
        .split_ascii_whitespace()
        .map(|s| s.parse().unwrap())
        .collect();

    // 得到人数
    let num_people = pass_list.len();
    assert!(0 < num_people);
    // 喊过的总次数
    let mut total_passes: u32 = pass_list.iter().sum();

    // 喊过的条件是:
    // 1. 当前数字是7的倍数
    // 2. 当前数字中包含7

    // 每个人真正喊过的次数
    let mut real_pass_list: Vec<usize> = vec![0; num_people];

    // 当前的喊的数字 k, 注意数字是从1开始
    let mut current_num = 1;
    // 当前喊数的人在队列中的位置, 从0开始计数
    let mut current_person = 0;

    // 一直循环, 直到喊过的次数用完了
    while total_passes > 0 {
        if current_num % 7 == 0 && number_digits_contains(current_num, 7) {
            // 这个人要喊过
            real_pass_list[current_person] += 1;
            total_passes -= 1;
        }
        current_num += 1;
        current_person = (current_person + 1) % num_people;
    }

    // 打印结果
    let s = real_pass_list
        .into_iter()
        .map(|x| x.to_string())
        .collect::<Vec<String>>()
        .join(" ");
    println!("{s}");
}

fn main() {
    solution();
}