8.6 แบบฝึกหัด
เขียนแต่ละข้อเป็นไฟล์ใหม่ใน Code::Blocks รันแล้วเทียบกับผลลัพธ์ที่ต้องได้ให้ตรงทุกตัวอักษร รวมถึงช่องว่างและการขึ้นบรรทัด ติดจริงๆ ค่อยเปิดคำใบ้ และเปิดเฉลยหลังทำเสร็จแล้วเท่านั้น
ข้อ 1 ป้ายชื่อมีกรอบ
ร้านป้ายหน้าโรงเรียนรับทำป้ายชื่อติดโต๊ะ ป้ายทุกแผ่นมีกรอบเป็นเครื่องหมาย # ล้อมรอบชื่อ และเว้นที่ว่างระหว่างกรอบกับชื่อ P ช่องทุกด้าน ทั้งซ้าย ขวา บน และล่าง ให้เขียนโปรแกรมพิมพ์ป้ายของชื่อ S
ถ้าชื่อยาว L ตัวอักษร ป้ายจะกว้าง L + 2P + 2 ตัวอักษร และสูง 2P + 3 บรรทัด ดังนี้
- บรรทัดแรกและบรรทัดสุดท้ายเป็น
#เต็มความกว้าง - P บรรทัดถัดจากบรรทัดแรก และ P บรรทัดก่อนบรรทัดสุดท้าย ขึ้นต้นและลงท้ายด้วย
#ตรงกลางเป็นช่องว่างทั้งหมด - บรรทัดกลางขึ้นต้นด้วย
#ตามด้วยช่องว่าง P ช่อง ชื่อ S ช่องว่าง P ช่อง และ#
ข้อมูลเข้า
บรรทัดเดียว มีชื่อ S และจำนวนเต็ม P คั่นด้วยช่องว่าง S ประกอบด้วยตัวอักษรภาษาอังกฤษหรือตัวเลขเท่านั้น ยาว 1 ถึง 50 ตัว และ 0 ≤ P ≤ 5
ข้อมูลออก
ป้ายชื่อ 2P + 3 บรรทัด ตามรูปแบบข้างบน
POSN 1########
# #
# POSN #
# #
########Ann 0#####
#Ann#
#####ดูคำใบ้
ป้ายมีบรรทัดแค่สามแบบ คือบรรทัดขอบ บรรทัดว่าง และบรรทัดชื่อ เขียน print_repeat(char symbol, int count) แบบ print_row ในหน้า 8.1 ก่อน แล้วสร้าง print_border(int width) กับ print_blank(int width) จากมัน main จะเหลือแค่เรียกฟังก์ชันตามลำดับบรรทัด ลองกับ P = 0 ด้วย ป้ายต้องเหลือแค่สามบรรทัด
ดูเฉลย
#include <stdio.h>
#include <string.h>
char name[55];
void print_repeat(char symbol, int count)
{
for (int i = 0; i < count; i++) {
printf("%c", symbol);
}
}
void print_border(int width)
{
print_repeat('#', width);
printf("\n");
}
void print_blank(int width)
{
printf("#");
print_repeat(' ', width - 2);
printf("#\n");
}
int main()
{
int padding;
scanf("%s %d", name, &padding);
int width = strlen(name) + 2 * padding + 2;
print_border(width);
for (int i = 0; i < padding; i++) {
print_blank(width);
}
printf("#");
print_repeat(' ', padding);
printf("%s", name);
print_repeat(' ', padding);
printf("#\n");
for (int i = 0; i < padding; i++) {
print_blank(width);
}
print_border(width);
return 0;
}ข้อ 2 ตั๋วผลบวกหลักสูงสุด
งานวัดแจกตั๋วจับรางวัล N ใบ ตั๋วแต่ละใบมีเลขเป็นจำนวนเต็ม กติกาคือเอาเลขโดดทุกหลักของเลขบนตั๋วมาบวกกัน ใบที่ได้ผลบวกมากที่สุดเป็นผู้ชนะ เช่น ตั๋วเลข 4096 ได้ 4 + 0 + 9 + 6 = 19 ถ้ามีหลายใบที่ได้ผลบวกมากที่สุดเท่ากัน ใบที่มีเลขน้อยที่สุดเป็นผู้ชนะ ตั๋วหลายใบอาจมีเลขซ้ำกันได้
ให้หาเลขบนตั๋วที่ชนะ และผลบวกเลขโดดของตั๋วใบนั้น
ข้อมูลเข้า
บรรทัดแรกมีจำนวนเต็ม N โดยที่ 1 ≤ N ≤ 100000
บรรทัดที่สองมีเลขบนตั๋ว N ใบ คั่นด้วยช่องว่าง แต่ละเลขเป็นจำนวนเต็มตั้งแต่ 0 ถึง 1000000000
ข้อมูลออก
บรรทัดเดียว มีเลขบนตั๋วที่ชนะ และผลบวกเลขโดดของตั๋วใบนั้น คั่นด้วยช่องว่าง
5
4096 512 77 1999 301999 284
2899 45 1999 6001999 28ดูคำใบ้
เขียน int digit_sum(int n) ที่ใช้ % 10 กับ /= 10 แบบหน้า 4.5 แล้ว main ทำแค่หาค่ามากสุดแบบหน้า 5.2 โดยเก็บทั้งเลขตั๋วและผลบวกของใบที่ดีที่สุดไว้ ตอนผลบวกเท่ากัน ต้องเทียบเลขตั๋วด้วย ใบที่มาก่อนไม่ได้ชนะเสมอไป และอย่าลืมตั๋วเลข 0 ซึ่งผลบวกเป็น 0
ดูเฉลย
#include <stdio.h>
int digit_sum(int n)
{
int sum = 0;
while (n > 0) {
sum += n % 10;
n /= 10;
}
return sum;
}
int main()
{
int n;
scanf("%d", &n);
int best_ticket = -1;
int best_sum = -1;
for (int i = 0; i < n; i++) {
int ticket;
scanf("%d", &ticket);
int sum = digit_sum(ticket);
if (sum > best_sum || (sum == best_sum && ticket < best_ticket)) {
best_ticket = ticket;
best_sum = sum;
}
}
printf("%d %d\n", best_ticket, best_sum);
return 0;
}ข้อ 3 วิ่งรอบสวน
ทุกเย็นน้องวิ่งรอบสวนสาธารณะ โดยวิ่งผ่านจุดพัก N จุดตามลำดับ เริ่มจากจุดที่ 1 ไปจุดที่ 2 จุดที่ 3 จนถึงจุดที่ N แล้ววิ่งกลับมาที่จุดที่ 1 อีกครั้งเพื่อจบรอบ ระหว่างสองจุดวิ่งเป็นเส้นตรงเสมอ จุดแต่ละจุดบอกเป็นพิกัด (x, y) หน่วยเป็นเมตร ระยะระหว่างจุด (x1, y1) กับ (x2, y2) คือรากที่สองของ (x2 - x1)2 + (y2 - y1)2
ให้หาระยะทางรวมของหนึ่งรอบ และระยะของช่วงที่ยาวที่สุดในรอบนั้น ช่วงหนึ่งคือการวิ่งจากจุดหนึ่งไปจุดถัดไป รวมถึงช่วงสุดท้ายที่วิ่งจากจุดที่ N กลับมาจุดที่ 1 ถ้ามีจุดเดียว น้องยืนอยู่กับที่ ระยะทั้งสองเป็น 0
ข้อมูลเข้า
บรรทัดแรกมีจำนวนเต็ม N โดยที่ 1 ≤ N ≤ 1000
อีก N บรรทัดต่อมา บรรทัดที่ i มีจำนวนเต็ม x และ y ของจุดที่ i คั่นด้วยช่องว่าง โดยที่ -10000 ≤ x, y ≤ 10000 จุดหลายจุดอาจอยู่ที่เดียวกันได้
ข้อมูลออก
บรรทัดแรกพิมพ์ระยะทางรวมของหนึ่งรอบ บรรทัดที่สองพิมพ์ระยะของช่วงที่ยาวที่สุด ทั้งสองค่าเป็นทศนิยม 2 ตำแหน่ง
4
0 0
3 0
3 4
0 414.00
4.003
0 0
5 2
1 617.12
6.08ดูคำใบ้
เก็บพิกัดไว้ในอาเรย์ แล้วเขียน double distance(int x1, int y1, int x2, int y2) แบบหน้า 8.5 จุดถัดจากจุดที่ i คือจุดที่ i + 1 ยกเว้นจุดสุดท้ายที่ต้องกลับไปจุดแรก ใช้ (i + 1) % n จะได้ตำแหน่งถัดไปแบบวนรอบโดยไม่ต้องแยกกรณี อย่าลืมช่วงขากลับ ตัวอย่างแรกมีช่วงขากลับยาว 4 เมตร และพิมพ์ด้วย %.2f
ดูเฉลย
#include <stdio.h>
#include <math.h>
int xs[1000];
int ys[1000];
double distance(int x1, int y1, int x2, int y2)
{
double dx = x2 - x1;
double dy = y2 - y1;
return sqrt(dx * dx + dy * dy);
}
int main()
{
int n;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
scanf("%d %d", &xs[i], &ys[i]);
}
double total = 0;
double longest = 0;
for (int i = 0; i < n; i++) {
int next = (i + 1) % n;
double leg = distance(xs[i], ys[i], xs[next], ys[next]);
total += leg;
if (leg > longest) {
longest = leg;
}
}
printf("%.2f\n", total);
printf("%.2f\n", longest);
return 0;
}ข้อ 4 จำนวนเฉพาะกลับหลัง
จำนวนเฉพาะคือจำนวนเต็มที่มากกว่า 1 และมีตัวหารที่เป็นจำนวนเต็มบวกแค่ 1 กับตัวมันเอง ครูคณิตศาสตร์ชอบจำนวนเฉพาะแบบพิเศษ คือจำนวนเฉพาะที่พอเขียนกลับหลังแล้วยังเป็นจำนวนเฉพาะอยู่ เช่น 13 กลับหลังได้ 31 ซึ่งเป็นจำนวนเฉพาะทั้งคู่ 11 กลับหลังได้ 11 ตัวเดิมก็นับ แต่ 19 กลับหลังได้ 91 = 7 × 13 ไม่นับ และ 91 เองก็ไม่นับเพราะไม่ใช่จำนวนเฉพาะ
เวลากลับหลัง ถ้ามีเลข 0 นำหน้าให้ตัดทิ้ง เช่น 1201 กลับหลังได้ 1021 ส่วน 3700 กลับหลังได้ 73
ให้นับว่าตั้งแต่ A ถึง B (รวม A และ B) มีจำนวนเต็ม n กี่ตัว ที่ n เป็นจำนวนเฉพาะ และ n ที่กลับหลังแล้วก็เป็นจำนวนเฉพาะด้วย
ข้อมูลเข้า
บรรทัดเดียว มีจำนวนเต็ม A และ B คั่นด้วยช่องว่าง โดยที่ 1 ≤ A ≤ B ≤ 100000
ข้อมูลออก
จำนวนของ n ที่ตรงเงื่อนไข
1 20790 20013ดูคำใบ้
แยกเป็นสองฟังก์ชัน is_prime(n) แบบหน้า 8.5 และ reverse_number(n) ที่หยิบหลักขวาสุดด้วย % 10 มาต่อท้ายผลด้วย result * 10 + digit ทีละหลัก เลข 0 นำหน้าจะหายไปเอง แล้ว main เหลือเงื่อนไขเดียว is_prime(n) && is_prime(reverse_number(n)) ระวัง 1 ซึ่งไม่ใช่จำนวนเฉพาะ
ดูเฉลย
#include <stdio.h>
int is_prime(int n)
{
if (n < 2) {
return 0;
}
for (long long i = 2; i * i <= n; i++) {
if (n % i == 0) {
return 0;
}
}
return 1;
}
int reverse_number(int n)
{
int result = 0;
while (n > 0) {
result = result * 10 + n % 10;
n /= 10;
}
return result;
}
int main()
{
int a, b;
scanf("%d %d", &a, &b);
int count = 0;
for (int n = a; n <= b; n++) {
if (is_prime(n) && is_prime(reverse_number(n))) {
count++;
}
}
printf("%d\n", count);
return 0;
}ข้อ 5 ห้องไหนเก่งกว่า
ม.3/1 กับ ม.3/2 สอบคณิตศาสตร์ข้อสอบชุดเดียวกัน ห้อง A มีนักเรียน N คน ห้อง B มีนักเรียน M คน ครูอยากเทียบสองห้อง โดยดูคะแนนสูงสุดและต่ำสุดของแต่ละห้อง แล้วดูว่าห้องไหนมีคะแนนเฉลี่ยสูงกว่า
คะแนนเฉลี่ยของห้องคือผลรวมคะแนนของทุกคนในห้องหารด้วยจำนวนคนในห้อง โดยไม่ปัดเศษ
ข้อมูลเข้า
บรรทัดที่ 1 มีจำนวนเต็ม N โดยที่ 1 ≤ N ≤ 1000
บรรทัดที่ 2 มีคะแนนของนักเรียนห้อง A ทั้ง N คน คั่นด้วยช่องว่าง
บรรทัดที่ 3 มีจำนวนเต็ม M โดยที่ 1 ≤ M ≤ 1000
บรรทัดที่ 4 มีคะแนนของนักเรียนห้อง B ทั้ง M คน คั่นด้วยช่องว่าง
คะแนนทุกค่าเป็นจำนวนเต็มตั้งแต่ 0 ถึง 100
ข้อมูลออก
บรรทัดที่ 1 พิมพ์คะแนนสูงสุดและต่ำสุดของห้อง A คั่นด้วยช่องว่าง
บรรทัดที่ 2 พิมพ์คะแนนสูงสุดและต่ำสุดของห้อง B คั่นด้วยช่องว่าง
บรรทัดที่ 3 พิมพ์ A ถ้าห้อง A มีคะแนนเฉลี่ยสูงกว่า พิมพ์ B ถ้าห้อง B สูงกว่า หรือพิมพ์ SAME ถ้าเท่ากันพอดี
5
62 88 75 91 70
4
80 95 95 6091 62
95 60
B2
1 2
1
12 1
1 1
Aดูคำใบ้
งานเดียวกันทำกับสองห้อง จึงเขียนฟังก์ชันที่รับอาเรย์กับความยาวแบบหน้า 8.3 ชุดเดียว คือ read_array max_of_array min_of_array sum_of_array แล้วเรียกห้องละครั้ง ส่วนการเทียบค่าเฉลี่ย ถ้าหาร int ด้วย int จะตัดเศษทิ้ง ค่าเฉลี่ย 1.5 กับ 1 จะกลายเป็นเท่ากัน ให้ใช้วิธีเลี่ยงการหารในหน้า 5.2 คือเทียบ sumA × M กับ sumB × N แทน
ดูเฉลย
#include <stdio.h>
int room_a[1000];
int room_b[1000];
void read_array(int values[], int n)
{
for (int i = 0; i < n; i++) {
scanf("%d", &values[i]);
}
}
int max_of_array(int values[], int n)
{
int best = values[0];
for (int i = 1; i < n; i++) {
if (values[i] > best) {
best = values[i];
}
}
return best;
}
int min_of_array(int values[], int n)
{
int worst = values[0];
for (int i = 1; i < n; i++) {
if (values[i] < worst) {
worst = values[i];
}
}
return worst;
}
int sum_of_array(int values[], int n)
{
int sum = 0;
for (int i = 0; i < n; i++) {
sum += values[i];
}
return sum;
}
int main()
{
int n, m;
scanf("%d", &n);
read_array(room_a, n);
scanf("%d", &m);
read_array(room_b, m);
printf("%d %d\n", max_of_array(room_a, n), min_of_array(room_a, n));
printf("%d %d\n", max_of_array(room_b, m), min_of_array(room_b, m));
int left = sum_of_array(room_a, n) * m;
int right = sum_of_array(room_b, m) * n;
if (left > right) {
printf("A\n");
} else if (left < right) {
printf("B\n");
} else {
printf("SAME\n");
}
return 0;
}ข้อ 6 รวมสูตรขนม
สูตรขนมของคุณยายเขียนปริมาณวัตถุดิบเป็นเศษส่วนของถ้วยตวงทั้งหมด เช่น แป้ง 3/4 ถ้วย น้ำตาล 1/3 ถ้วย กะทิ 5/6 ถ้วย หลานอยากรู้ว่าวัตถุดิบทั้ง N อย่างรวมกันเป็นกี่ถ้วย โดยตอบเป็นเศษส่วนอย่างต่ำ
เศษส่วนอย่างต่ำ p/q คือเศษส่วนที่ p กับ q ไม่มีตัวหารร่วมอื่นนอกจาก 1 เช่น 6/4 ต้องตอบเป็น 3/2 ถ้าผลรวมเป็นจำนวนเต็มพอดี ให้ตอบเป็นจำนวนเต็มเฉยๆ เช่น 2/1 ให้ตอบ 2
ข้อมูลเข้า
บรรทัดแรกมีจำนวนเต็ม N โดยที่ 1 ≤ N ≤ 20
อีก N บรรทัดต่อมา บรรทัดละหนึ่งเศษส่วนในรูป a/b ไม่มีช่องว่าง โดยที่ 1 ≤ a ≤ 1000 และ 1 ≤ b ≤ 20 เศษส่วนในข้อมูลเข้าอาจยังไม่เป็นอย่างต่ำ และอาจมากกว่าหนึ่งถ้วยก็ได้
ข้อมูลออก
ผลรวมเป็นเศษส่วนอย่างต่ำในรูป p/q หรือพิมพ์ p อย่างเดียวถ้า q เป็น 1
3
3/4
1/3
5/623/123
1/2
3/4
3/42ดูคำใบ้
รับเศษส่วนด้วย scanf("%d/%d", ...) แบบตัวคั่นในหน้า 2.3 เก็บผลรวมไว้เป็น p/q เริ่มที่ 0/1 แล้วบวกทีละตัวด้วยสูตร p/q + a/b = (p × b + a × q)/(q × b) หลังบวกทุกครั้ง ให้หารทั้ง p และ q ด้วย gcd(p, q) ของหน้า 8.5 ถ้ารอทำอย่างต่ำตอนท้ายทีเดียว ส่วนจะเป็นผลคูณของตัวส่วนทั้ง 20 ตัว ซึ่งล้น long long ได้ ระหว่างทาง p × b และ q × b ก็เกิน int ได้ จึงต้องใช้ long long ทั้ง p q และพารามิเตอร์ของ gcd
ดูเฉลย
#include <stdio.h>
long long gcd(long long a, long long b)
{
while (b != 0) {
long long remainder = a % b;
a = b;
b = remainder;
}
return a;
}
int main()
{
int n;
scanf("%d", &n);
long long top = 0;
long long bottom = 1;
for (int i = 0; i < n; i++) {
int a, b;
scanf("%d/%d", &a, &b);
top = top * b + a * bottom;
bottom = bottom * b;
long long g = gcd(top, bottom);
top /= g;
bottom /= g;
}
if (bottom == 1) {
printf("%lld\n", top);
} else {
printf("%lld/%lld\n", top, bottom);
}
return 0;
}ข้อ 7 นับวันระหว่างสองวันที่
แอปนับวันของโรงเรียนต้องตอบคำถาม Q ข้อ แต่ละข้อถามว่า จากวันที่หนึ่งไปถึงอีกวันที่หนึ่ง ห่างกันกี่วัน เช่น จากวันที่ 28 กุมภาพันธ์ 2024 ถึงวันที่ 1 มีนาคม 2024 ห่างกัน 2 วัน เพราะปี 2024 มีวันที่ 29 กุมภาพันธ์คั่นอยู่ ถ้าเป็นวันเดียวกัน ห่างกัน 0 วัน
เดือน 4 6 9 11 มี 30 วัน เดือน 2 มี 29 วันในปีอธิกสุรทิน และ 28 วันในปีอื่น เดือนที่เหลือมี 31 วัน ปีอธิกสุรทินคือปีที่หารด้วย 4 ลงตัวแต่หารด้วย 100 ไม่ลงตัว หรือปีที่หารด้วย 400 ลงตัว ปีทุกปีในข้อนี้เป็นปีคริสต์ศักราช
ข้อมูลเข้า
บรรทัดแรกมีจำนวนเต็ม Q โดยที่ 1 ≤ Q ≤ 100000
อีก Q บรรทัดต่อมา บรรทัดละหนึ่งคำถาม มีจำนวนเต็มหกตัว D1 M1 Y1 D2 M2 Y2 คั่นด้วยช่องว่าง คือวันที่เริ่มและวันที่จบ ทั้งสองเป็นวันที่ที่มีอยู่จริง ปีอยู่ระหว่าง 1900 ถึง 2600 และวันที่จบไม่มาก่อนวันที่เริ่ม
ข้อมูลออก
Q บรรทัด บรรทัดที่ i เป็นจำนวนวันจากวันที่เริ่มถึงวันที่จบของคำถามที่ i
3
28 2 2024 1 3 2024
21 10 2026 21 10 2026
1 1 2026 1 1 20272
0
3653
28 2 1900 1 3 1900
28 2 2000 1 3 2000
31 12 2025 1 1 20261
2
1ดูคำใบ้
เดินทีละวันแบบข้อวันพรุ่งนี้ในบทที่ 3 ถูกต้อง แต่คำถามหนึ่งข้ออาจห่างกันถึงสองแสนกว่าวัน คูณกับแสนคำถามแล้วช้าเกินไป ให้เปลี่ยนวันที่ทุกวันเป็นเลขลำดับวันนับจากวันที่ 1 มกราคม 1900 แทน แล้วคำตอบคือเลขลำดับของวันจบลบเลขลำดับของวันเริ่ม แบ่งเป็นสามฟังก์ชัน is_leap(year) days_in_month(month, year) และ day_number(day, month, year) ที่บวกจำนวนวันของทุกปีก่อนหน้า ทุกเดือนก่อนหน้าในปีนั้น แล้วบวก day ทดสอบกับ 28 กุมภาพันธ์ถึง 1 มีนาคมของปี 1900 2000 และ 2024
ดูเฉลย
#include <stdio.h>
int is_leap(int year)
{
return (year % 4 == 0 && year % 100 != 0) || year % 400 == 0;
}
int days_in_month(int month, int year)
{
if (month == 2) {
return is_leap(year) ? 29 : 28;
}
if (month == 4 || month == 6 || month == 9 || month == 11) {
return 30;
}
return 31;
}
int day_number(int day, int month, int year)
{
int total = 0;
for (int y = 1900; y < year; y++) {
total += is_leap(y) ? 366 : 365;
}
for (int m = 1; m < month; m++) {
total += days_in_month(m, year);
}
return total + day;
}
int main()
{
int q;
scanf("%d", &q);
for (int i = 0; i < q; i++) {
int d1, m1, y1, d2, m2, y2;
scanf("%d %d %d %d %d %d", &d1, &m1, &y1, &d2, &m2, &y2);
printf("%d\n", day_number(d2, m2, y2) - day_number(d1, m1, y1));
}
return 0;
}ข้อ 8 ป้ายไฟตัวเลข
ป้ายไฟหน้าห้องสมุดแสดงตัวเลขด้วยหลอดไฟ 7 ท่อน แต่ละหลักประกอบด้วยท่อนบน (a) ท่อนขวาบน (b) ท่อนขวาล่าง (c) ท่อนล่าง (d) ท่อนซ้ายล่าง (e) ท่อนซ้ายบน (f) และท่อนกลาง (g) ตัวเลขแต่ละตัวเปิดท่อนต่อไปนี้
| เลข | ท่อนที่เปิด | เลข | ท่อนที่เปิด |
|---|---|---|---|
| 0 | a b c d e f | 5 | a c d f g |
| 1 | b c | 6 | a c d e f g |
| 2 | a b d e g | 7 | a b c |
| 3 | a b c d g | 8 | a b c d e f g |
| 4 | b c f g | 9 | a b c d f g |
ป้ายปรับขนาดได้ด้วยค่า S ตัวเลขหนึ่งหลักกว้าง S + 2 คอลัมน์ สูง 2S + 3 แถว ช่องที่ไฟติดพิมพ์เป็น # ช่องที่ไฟดับพิมพ์เป็น . นับแถวจาก 1 ด้านบน และนับคอลัมน์จาก 1 ด้านซ้าย
- ท่อน a อยู่แถวที่ 1 ท่อน g อยู่แถวที่ S + 2 ท่อน d อยู่แถวที่ 2S + 3 ทั้งสามท่อนกินคอลัมน์ที่ 2 ถึง S + 1
- ท่อน f กับ b อยู่แถวที่ 2 ถึง S + 1 ท่อน e กับ c อยู่แถวที่ S + 3 ถึง 2S + 2 ท่อน f กับ e อยู่คอลัมน์ที่ 1 ท่อน b กับ c อยู่คอลัมน์ที่ S + 2
- มุมทั้งสี่และช่องอื่นที่ไม่อยู่ในท่อนใดเป็น
.เสมอ
ตัวเลขหลายหลักวางเรียงจากซ้ายไปขวาตามลำดับ ระหว่างสองหลักที่ติดกันคั่นด้วยคอลัมน์ของ . หนึ่งคอลัมน์ ดูรูปจากตัวอย่าง
ข้อมูลเข้า
บรรทัดเดียว มีจำนวนเต็ม S และตัวเลข D คั่นด้วยช่องว่าง โดยที่ 1 ≤ S ≤ 10 และ D เป็นตัวเลข 0 ถึง 9 เรียงติดกัน 1 ถึง 20 หลัก D อาจขึ้นต้นด้วย 0 และต้องแสดง 0 นั้นด้วย
ข้อมูลออก
รูปป้ายไฟ 2S + 3 บรรทัด
1 0123456789.#.......#...#.......#...#...#...#...#.
#.#...#...#...#.#.#.#...#.....#.#.#.#.#
.........#...#...#...#...#.......#...#.
#.#...#.#.....#...#...#.#.#...#.#.#...#
.#.......#...#.......#...#.......#...#.2 2026.##...##...##...##.
...#.#..#....#.#...
...#.#..#....#.#...
.##........##...##.
#....#..#.#....#..#
#....#..#.#....#..#
.##...##...##...##.ดูคำใบ้
รับ D เป็นสตริงด้วย %s เพราะอาจขึ้นต้นด้วย 0 และยาวเกิน long long เก็บตารางท่อนไว้เป็นอาเรย์ของสตริง เช่น "abcdef" สำหรับเลข 0 แล้วเขียน int is_on(int digit, char segment) ที่ไล่หาตัวอักษรในสตริงนั้น ป้ายมีแถวแค่สองแบบ แถวท่อนนอน (a g d) กับแถวท่อนตั้ง (f b หรือ e c) จึงเขียนสองฟังก์ชัน print_horizontal(char segment) และ print_vertical(char left, char right) ที่พิมพ์ทั้งแถวครบทุกหลัก แล้ว main เรียกตามลำดับแถว ระวังอย่าพิมพ์ . คั่นหลังหลักสุดท้าย
ดูเฉลย
#include <stdio.h>
char segments[10][8] = {"abcdef", "bc", "abdeg", "abcdg", "bcfg",
"acdfg", "acdefg", "abc", "abcdefg", "abcdfg"};
char digits[25];
int size;
int is_on(int digit, char segment)
{
for (int i = 0; segments[digit][i] != '\0'; i++) {
if (segments[digit][i] == segment) {
return 1;
}
}
return 0;
}
void print_repeat(char symbol, int count)
{
for (int i = 0; i < count; i++) {
printf("%c", symbol);
}
}
void print_horizontal(char segment)
{
for (int i = 0; digits[i] != '\0'; i++) {
if (i > 0) {
printf(".");
}
printf(".");
print_repeat(is_on(digits[i] - '0', segment) ? '#' : '.', size);
printf(".");
}
printf("\n");
}
void print_vertical(char left, char right)
{
for (int i = 0; digits[i] != '\0'; i++) {
int digit = digits[i] - '0';
if (i > 0) {
printf(".");
}
printf("%c", is_on(digit, left) ? '#' : '.');
print_repeat('.', size);
printf("%c", is_on(digit, right) ? '#' : '.');
}
printf("\n");
}
int main()
{
scanf("%d %s", &size, digits);
print_horizontal('a');
for (int r = 0; r < size; r++) {
print_vertical('f', 'b');
}
print_horizontal('g');
for (int r = 0; r < size; r++) {
print_vertical('e', 'c');
}
print_horizontal('d');
return 0;
}