{ }codelper
不换行输出P0404

用数字字体印横幅

数字横幅机用输入给出的字体把数字字符串印成大字。
字体中,数字 0 到 9 每个都有一幅图。
一幅图有 h 行,每行是只由 # 和 . 组成的字符串。
一幅图的各行长度都相同,这个长度叫作该数字的宽度。
不同数字的宽度可以不同。
把要印的数字字符串 s 的数字从左到右依次放进块里。
在一个块里,图从左到右并排摆放,相邻两幅图之间插入一列只由 . 组成的列。
块的宽度等于其中各图宽度之和加上插入的列数。
s 的第一个数字放进第一个块。
从下一个数字起,如果放进当前块后块的宽度仍不超过 W,就放进当前块;如果会超过 W,就开始一个新块并放进去。
按块产生的顺序输出。
一个块输出 h 行,其中第 k 行是把块里各图的第 k 行从左到右用一个 . 隔开连起来的结果。
因此每行的长度等于该块的宽度,行首和行尾都不会出现插入的 .。
相邻两个块之间输出一个空行。
第一个块之前和最后一个块之后都不输出空行。

输入
第一行给出图的高度 h 和块宽度的上限 W,用一个空格隔开。
接下来 10×h 行依次给出 0 的图、1 的图、…、9 的图,每幅 h 行。
最后一行给出数字字符串 s。
1 ≤ h ≤ 8。
图的宽度在 1 到 8 之间,且最宽的图的宽度 ≤ W ≤ 80,所以只放一幅图的块不会超过 W。
s 只由数字 0~9 组成,长度在 1 到 1,000 之间。
输出
每个块 h 行,相邻块之间一个空行
样例 1 · stdin
3 7
###
#.#
###
#
#
#
##.
.#.
.##
###
.##
###
#.#
###
..#
.##
.#.
##.
#..
###
###
##
.#
.#
###
###
###
###
###
..#
01230
stdout
###.#
#.#.#
###.#

##..###
.#...##
.##.###

###
#.#
###
main.py
输入(stdin)

运行时这些行会依次作为 input()/标准输入传入(运行中不会等待输入)。

$ 就绪

请在电脑上打开以编写和运行代码。在手机上可以查看题目和题解。

其他语言怎么写?查看各语言题解 · 8 种语言题解

这道题要把几幅图的片段接着写成一行之后才换行。
所以外层循环是行(0 到 h-1),内层循环是块里的图——如果把一幅图的 h 行全部印完再印下一幅,数字会往下堆,而不是并排。
不换行接着输出的写法因语言而异。
Python 用 print(x, end="")(直接 print(x) 会在末尾加 \n),JS/TS 用 process.stdout.write(x)(console.log 总会换行;每个片段都调用一次 write、调用几万次会很慢,所以题解先把片段接成字符串再一次写出),Java 有 print 和 println(题解为了快,先写进 PrintWriter,最后 flush()),C# 有 Write 和 WriteLine,C 用 fputs、putchar、printf,C++ 用 std::cout << x(换行要自己写 '\n'),Craykon 有 控制台.接着输出(x) 和 控制台.输出(x)。
在 Craykon 里只想换行时写 控制台.输出("")。
陷阱一:用了会换行的输出函数。
Python 写 print(glyph[row]),或在 C 里用 puts 代替 fputs(puts 会在末尾加换行),每个片段后都会换行,示例的第一行就只剩 ###。
陷阱二:每幅图后面都加 .,行尾会多出一个 .(示例第一行变成 ###.#.)。
很多评测会忽略行尾空格,但 . 是可见字符,直接判错。
只在不是第一幅图时在前面加 .。
陷阱三:块宽度算错。
放进一幅图时,宽度增加的是图的宽度再加上间隔列的 1。
不算间隔列,示例中 0、1、2 会放进同一块(实际宽度 9);用 < W 代替 ≤ W 比较,宽度正好为 7 的第二块(2 和 3)会被拆成两块。
陷阱四:空行只放在块与块之间。
漏掉的话块会粘在一起;每个块前都放的话第一行会是空行。
从第二个块起在前面放一个空行即可。

Pythonmain.py · 31 行
import sys tokens = sys.stdin.read().split()h, w_max = int(tokens[0]), int(tokens[1])font = []for d in range(10):    font.append(tokens[2 + d * h: 2 + (d + 1) * h])s = tokens[2 + 10 * h] # 숫자들을 덩어리로 나눈다blocks = []width = 0for ch in s:    glyph = font[int(ch)]    gw = len(glyph[0])    if blocks and width + 1 + gw <= w_max:        blocks[-1].append(glyph)        width += 1 + gw    else:        blocks.append([glyph])        width = gw for b, block in enumerate(blocks):    if b > 0:        print()    for row in range(h):        for i, glyph in enumerate(block):            if i > 0:                print(".", end="")            print(glyph[row], end="")        print()
JavaScriptmain.js · 35 行
const tokens = require("fs").readFileSync(0, "utf8").trim().split(/\s+/);const h = Number(tokens[0]);const maxWidth = Number(tokens[1]);const font = [];for (let d = 0; d < 10; d++) font.push(tokens.slice(2 + d * h, 2 + (d + 1) * h));const s = tokens[2 + 10 * h]; // 숫자들을 덩어리로 나눈다const blocks = [];let width = 0;for (const ch of s) {  const glyph = font[Number(ch)];  const gw = glyph[0].length;  if (blocks.length > 0 && width + 1 + gw <= maxWidth) {    blocks[blocks.length - 1].push(glyph);    width += 1 + gw;  } else {    blocks.push([glyph]);    width = gw;  }} // console.log는 늘 줄을 바꾼다. 조각을 문자열에 이어 붙였다가 process.stdout.write로 한 번에 쓴다let out = "";blocks.forEach((block, b) => {  if (b > 0) out += "\n";  for (let row = 0; row < h; row++) {    block.forEach((glyph, i) => {      if (i > 0) out += ".";      out += glyph[row];    });    out += "\n";  }});process.stdout.write(out);
TypeScriptmain.ts · 36 行
import { readFileSync } from "node:fs";const tokens: string[] = readFileSync(0, "utf8").trim().split(/\s+/);const h: number = Number(tokens[0]);const maxWidth: number = Number(tokens[1]);const font: string[][] = [];for (let d = 0; d < 10; d++) font.push(tokens.slice(2 + d * h, 2 + (d + 1) * h));const s: string = tokens[2 + 10 * h]; // 숫자들을 덩어리로 나눈다const blocks: string[][][] = [];let width = 0;for (const ch of s) {  const glyph = font[Number(ch)];  const gw = glyph[0].length;  if (blocks.length > 0 && width + 1 + gw <= maxWidth) {    blocks[blocks.length - 1].push(glyph);    width += 1 + gw;  } else {    blocks.push([glyph]);    width = gw;  }} // console.log는 늘 줄을 바꾼다. 조각을 문자열에 이어 붙였다가 process.stdout.write로 한 번에 쓴다let out: string = "";blocks.forEach((block, b) => {  if (b > 0) out += "\n";  for (let row = 0; row < h; row++) {    block.forEach((glyph, i) => {      if (i > 0) out += ".";      out += glyph[row];    });    out += "\n";  }});process.stdout.write(out);
JavaMain.java · 48 行
import java.io.*;import java.util.*; public class Main {    public static void main(String[] args) throws IOException {        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));        StringTokenizer st = new StringTokenizer(in.readLine());        int h = Integer.parseInt(st.nextToken());        int maxWidth = Integer.parseInt(st.nextToken());        String[][] font = new String[10][h];        for (int d = 0; d < 10; d++)            for (int r = 0; r < h; r++)                font[d][r] = in.readLine().trim();        String s = in.readLine().trim();         // 숫자들을 덩어리로 나눈다        List<List<String[]>> blocks = new ArrayList<>();        int width = 0;        for (char ch : s.toCharArray()) {            String[] glyph = font[ch - '0'];            int gw = glyph[0].length();            if (!blocks.isEmpty() && width + 1 + gw <= maxWidth) {                blocks.get(blocks.size() - 1).add(glyph);                width += 1 + gw;            } else {                List<String[]> block = new ArrayList<>();                block.add(glyph);                blocks.add(block);                width = gw;            }        }         // print는 줄을 바꾸지 않고, println은 바꾼다        PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));        for (int b = 0; b < blocks.size(); b++) {            if (b > 0) out.println();            List<String[]> block = blocks.get(b);            for (int row = 0; row < h; row++) {                for (int i = 0; i < block.size(); i++) {                    if (i > 0) out.print('.');                    out.print(block.get(i)[row]);                }                out.println();            }        }        out.flush();    }}
C#Main.cs · 56 行
using System;using System.Collections.Generic;using System.IO; class Program{    static void Main()    {        string[] first = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries);        int h = int.Parse(first[0]);        int maxWidth = int.Parse(first[1]);        var font = new string[10][];        for (int d = 0; d < 10; d++)        {            font[d] = new string[h];            for (int r = 0; r < h; r++) font[d][r] = Console.ReadLine().Trim();        }        string s = Console.ReadLine().Trim();         // 숫자들을 덩어리로 나눈다        var blocks = new List<List<string[]>>();        int width = 0;        foreach (char ch in s)        {            string[] glyph = font[ch - '0'];            int gw = glyph[0].Length;            if (blocks.Count > 0 && width + 1 + gw <= maxWidth)            {                blocks[^1].Add(glyph);                width += 1 + gw;            }            else            {                blocks.Add(new List<string[]> { glyph });                width = gw;            }        }         // Write는 줄을 바꾸지 않고, WriteLine은 바꾼다        var output = new StreamWriter(Console.OpenStandardOutput());        for (int b = 0; b < blocks.Count; b++)        {            if (b > 0) output.WriteLine();            for (int row = 0; row < h; row++)            {                for (int i = 0; i < blocks[b].Count; i++)                {                    if (i > 0) output.Write('.');                    output.Write(blocks[b][i][row]);                }                output.WriteLine();            }        }        output.Flush();    }}
C++main.cpp · 42 行
#include <iostream>#include <string>#include <vector>using namespace std; int main() {    int h, maxWidth;    cin >> h >> maxWidth;    vector<vector<string>> font(10, vector<string>(h));    for (int d = 0; d < 10; d++)        for (int r = 0; r < h; r++) cin >> font[d][r];    string s;    cin >> s;     // 숫자들을 덩어리로 나눈다    vector<vector<int>> blocks;    int width = 0;    for (char ch : s) {        int digit = ch - '0';        int gw = (int)font[digit][0].size();        if (!blocks.empty() && width + 1 + gw <= maxWidth) {            blocks.back().push_back(digit);            width += 1 + gw;        } else {            blocks.push_back({digit});            width = gw;        }    }     // cout << 는 줄을 바꾸지 않는다. 줄바꿈은 '\n'으로 직접 넣는다    for (size_t b = 0; b < blocks.size(); b++) {        if (b > 0) cout << '\n';        for (int row = 0; row < h; row++) {            for (size_t i = 0; i < blocks[b].size(); i++) {                if (i > 0) cout << '.';                cout << font[blocks[b][i]][row];            }            cout << '\n';        }    }    return 0;}
Cmain.c · 42 行
#include <stdio.h>#include <string.h> char font[10][8][9]; /* 숫자 10개 × 줄 8개 × (글자 8개 + '\0') */char s[1001];int blockStart[1001]; /* 덩어리마다 첫 숫자의 자리 */ int main(void) {    int h, maxWidth;    scanf("%d %d", &h, &maxWidth);    for (int d = 0; d < 10; d++)        for (int r = 0; r < h; r++)            scanf("%8s", font[d][r]);    scanf("%1000s", s);    int n = (int)strlen(s);     /* 숫자들을 덩어리로 나눈다 */    int blocks = 0, width = 0;    for (int i = 0; i < n; i++) {        int gw = (int)strlen(font[s[i] - '0'][0]);        if (blocks > 0 && width + 1 + gw <= maxWidth) {            width += 1 + gw;        } else {            blockStart[blocks++] = i;            width = gw;        }    }    blockStart[blocks] = n;     /* puts는 끝에 줄바꿈을 붙이므로 fputs·putchar로 이어 쓴다 */    for (int b = 0; b < blocks; b++) {        if (b > 0) putchar('\n');        for (int row = 0; row < h; row++) {            for (int i = blockStart[b]; i < blockStart[b + 1]; i++) {                if (i > blockStart[b]) putchar('.');                fputs(font[s[i] - '0'][row], stdout);            }            putchar('\n');        }    }    return 0;}
Craykonmain.cray · 55 行
첫줄 = 控制台.读数字();h = 첫줄[0];최대너비 = 첫줄[1];글꼴 = [];循环 (d = 0; d < 10; d++){    그림 = [];    循环 (r = 0; r < h; r++)    {        그림.添加(控制台.读行().去空白());    }    글꼴.添加(그림);}s = 控制台.读行().去空白(); // 숫자들을 덩어리로 나눈다덩어리들 = [];너비 = 0;遍历 (c 在 s){    숫자 = c.转数字();    그림너비 = 글꼴[숫자][0].长度;    如果 (덩어리들.数量 > 0 && 너비 + 1 + 그림너비 <= 최대너비)    {        덩어리들[덩어리들.数量 - 1].添加(숫자);        너비 += 1 + 그림너비;    }    否则    {        덩어리들.添加([숫자]);        너비 = 그림너비;    }} // 콘솔.쓰기는 줄을 바꾸고, 콘솔.이어쓰기는 바꾸지 않는다循环 (b = 0; b < 덩어리들.数量; b++){    如果 (b > 0)    {        控制台.输出("");    }    덩어리 = 덩어리들[b];    循环 (줄 = 0; 줄 < h; 줄++)    {        循环 (i = 0; i < 덩어리.数量; i++)        {            如果 (i > 0)            {                控制台.接着输出(".");            }            控制台.接着输出(글꼴[덩어리[i]][줄]);        }        控制台.输出("");    }}