计算第k个答案———摩尔斯电码(可视化代码)

文章介绍了在没有电话的时代,摩尔斯电码的重要性。提供了一段C语言代码,该代码使用贪心算法计算给定长点和短点数量时,字典中第k个摩尔斯电码信号。代码包括计算组合数的函数和绘制摩尔斯电码的可视化部分,适用于n和m小于60的情况。
摘要由CSDN通过智能技术生成

题目 

摩尔斯电码字典
在没有电话的时代,摩尔斯电码是无线电传输领域中的一种常用代码。电码以短信号(短点,o)和长信号(长点,-)的不同组合表示各种文字。例如:o—表示英文字母J,而—表示英文字母M。
假设有一本以n个长点和m(n、m<=100)个短点组成的、包含所有信号的字典。例如:n=m=2,就会包含如下信号。
–oo
-o-o
-oo-
o–o
o-o-
oo–
这些信号已按照字典顺序排列好了。-的ASKII码是45,而o的ASCII码是111。因此,按照字典顺序,-在前,o在后。给定n和m时,编写代码计算出此字典的第k(k<=1,000,000,000,000)个信号。例如:上述字典的第四个信号是o–o。

代码比较长,但没有任何bug,并且加上了可视化。主要函数有两个,calculate()和computeKthMorseCode(),calculate函数用来计算C(n,k),数学公式转换为代码;computeKthMorseCode函数里的if条件采用了贪心算法思想。代码运行之前需要安装EasyX。


代码:

#include <stdio.h>
#include <stdlib.h>
#include <graphics.h>
#include <conio.h>
#include <windows.h>
#include <time.h>

// 计算组合数C(n, k)
long long calculate(int n, int k) {
    if (k == 0 || k == n)
        return 1;

    long long result = 1;
    int i;

    k = (k > n - k) ? n - k : k;

    for (i = 0; i < k; ++i) {
        result *= (n - i);
        result /= (i + 1);
    }

    return result;
}

// 计算组合数C(b, a)与k的比值,即k/C(b, a)
 double calculateCombination(int b, int a, long long k) {
    if (a == 0 || a == b)
        return k*1.00;

    a = (a > b - a) ? b - a : a;

    double result = 1;
    for (int i = 0; i < a; i++) 
    {
        result *= (i + 1);
        result /= (b - i);       
    }
    return result* k;
}

// 绘制信号点,矩形代表长点,圆形代表短点。
void drawSignal(int x, int y, bool isLong)
{
    setfillcolor(BLACK); // 设置填充颜色为黑色
    if (isLong) //判断是绘制矩形还是圆形信号 
    {
        int rectX = x + 5; 
        int rectY = y + 5; 
        rectangle(rectX, rectY, rectX + 10, rectY + 10); // 绘制矩形
        fillrectangle(rectX, rectY, rectX + 10, rectY + 10); // 在矩形内填充颜色
    }
    else {
        int circleX = x + 10; 
        int circleY = y + 10; 
        circle(circleX, circleY, 3); // 绘制圆形
        fillcircle(circleX, circleY, 3); // 在圆形内填充颜色
    }
}

//定义延迟函数用于延迟显示每个信号
void delay(int milliseconds)
{
    clock_t start_time = clock();//记录当前的时钟时间,即延时开始的时间。
    while ((clock() - start_time) * 1000 / CLOCKS_PER_SEC < milliseconds) 
        //将clock()函数的结果转化为以秒为单位的量,并与minlliseconds
    {
        // 空循环等待
    }
}

// 计算第k个摩尔斯电码
void computeKthMorseCode(int n, int m, long long k) {

    int totalSignals = n + m;
    int i = 0;
    int x = 100;  // 起始绘制位置的 x 坐标
    int y = 100;  // 起始绘制位置的 y 坐标

    initgraph(800, 600);  // 初始化图形界面

    setbkcolor(WHITE); // 设置背景色为白色
    cleardevice(); // 清空窗口内容


    // 添加说明文字
    settextstyle(20, 0, _T("黑体"));// 设置字体样式和大小
    settextcolor(BLACK);
    int textX = getmaxx() / 2 - textwidth("圆形代表短信号(o),矩形代表长信号(-)") / 2; // 计算文字的x坐标使其居中
    int textY = 50; // 文字的y坐标
    outtextxy(textX, textY, _T("圆形代表短信号(o),矩形代表长信号(-)")); // 绘制说明文字


    while (totalSignals > 0) {
        setcolor(BLACK); // 设置画笔颜色为黑色
        rectangle(x, y, x + 20, y + 20); // 绘制黑色边框格子

        // 如果剩余的信号中的长点数大于等于n,添加长点,即矩形
        if (n > 0 && calculateCombination(totalSignals - 1, n - 1, k) <=1.00) 
            //等价于calculate(totalSignals - 1, n - 1) >= k
        {
            drawSignal(x, y, true);//绘制矩形
            n--;
        }
        // 否则,添加短点,即圆形 
        else {
            drawSignal(x, y, false);//绘制圆形
            m--;
            if (totalSignals - 1 < 60) //[43,66]区间内任意一个数
            {
                k -= calculate(totalSignals - 1, n - 1);
            }
            else {
                k = 2107040442; 
            }
        }

        totalSignals--;
        i++;

        x += 20; // 移动到下一个格子位置

        if (i % 30 == 0) // 每绘制30个格子后换行
        {  
            x = 100;
            y += 20;
        }
        delay(200);  // 延迟显示每个信号点
    }
    
    while (!_kbhit()) //持续地检测键盘是否有输入
    {
        delay(200);  // 等待输入
    }
    closegraph();  // 关闭图形界面
}

int main() 
{
    int n, m;
    long long k;
    printf("请输入n的值: ");
    scanf_s("%d", &n);
    printf("请输入m的值: ");
    scanf_s("%d", &m);
    printf("请输入k的值: ");
    scanf_s("%lld", &k);
    if (k > 0 && calculateCombination(n + m, n, k)<=1.00){   
        computeKthMorseCode(n, m, k);
    }
    else {
        printf("输入的k值有误!");
    }
    return 0;
}

​

 这是没有可视化的代码,运行的时候没问题,但是m和n太大的时候其组合数会非常大,超出long long 类型的范围从而导致出错。输入的时候m+n最好要小于60。

#include <stdio.h>
#include <stdlib.h>
// 计算组合数C(n, k)
long long calculateCombination(int n, int k) {
    if (k == 0 || k == n)
        return 1;
    long long result = 1;
    int i;
    k = (k > n - k) ? n - k : k;
    for (i = 0; i < k; ++i) {
        result *= (n - i);
        result /= (i + 1);
    }
    return result;
}
// 计算第k个摩尔斯电码
void computeKthMorseCode(int n, int m, int k, char* morse) {
    int totalSignals = n + m;
    int i = 0;
    while (totalSignals > 0) {
        // 如果剩余的信号中的长点数大于等于n,添加长点
        if (n > 0 && calculateCombination(totalSignals - 1, n - 1) >= k) {
            morse[i] = '-';
            --n;
        }
        // 否则,添加短点
        else {
            morse[i] = '.';
            --m;
            k -= calculateCombination(totalSignals - 1, n - 1);
        }
        --totalSignals;
        ++i;
    }
    morse[i] = '\0';
}
int main() {
    int n, m, k;
    printf("Enter the number of long signals (n): ");
    scanf_s("%d", &n);
    printf("Enter the number of short signals (m): ");
    scanf_s("%d", &m);
    printf("Enter the value of k: ");
    scanf_s("%d", &k);
    char* morse = (char*)malloc(sizeof(char) * (n + m + 1)); // 分配足够的内存来存储摩尔斯电码
    computeKthMorseCode(n, m, k, morse);
    printf("The %dth Morse code is: %s\n", k, morse);
    free(morse);
    return 0;
}



 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值