笔试题练习(四)

1.   成语纠错

问题背景

你的任务是给一个错误的四字成语进行纠错,找到它的正确写法。具体来说,你只允许修改四个汉字中的其中一个,使得修改后的成语在给定的成语列表中出现。原先的错误成语保证不在成语列表中出现。

有时,这样的纠错结果并不惟一。例如一糯千金可以改为一字千金也可以改成一诺千金。但由于是同音字,一糯千金实为一诺千金的可能性比较大。

因此,我们还将提供一个汉字分类表,要求修改前后的两个字必须属于同一个分类。

在这样的限制下,我们保证成语纠错的结果惟一。

注意

1、汉字均采用GBK编码(参见FAQ)

2、每个汉字分类至少包含两个汉字,同一个汉字可能出现在多个类别中。

3、成语列表中的成语都是真实存在的四字成语。成语列表和待纠错成语中的所有汉字均在汉字分类表中的至少一个分类中出现。

输入格式

输入第一行包含两个整数n,m(1<=n<=200,1<=m<=20000)n表示汉字类别的个数,m表示成语的个数。

以下n行每行用一个无空白分隔符(空格、TAB)的汉字串表示一个分类中的所有汉字。注意,该汉字串最多可能包含200个汉字。

以下m行为成语列表,每行一个成语,恰好四个汉字。

最后一行为待纠错的成语,恰好四个汉字,且不在成语列表中出现。

输出格式

仅一行,为一个四字成语。在修改必须在同一分类中进行的限制下,输入数据保证纠错结果惟一。

样例输入

7    3

糯诺挪喏懦

字自子紫籽

前钱千牵浅

进近今仅紧金斤尽劲

完万

水睡税

山闪衫善扇杉

一诺千金

一字千金

万水千山

一糯千金

样例输出

一诺千金

import  java.io.IOException;
import  java.util.ArrayList;
import  java.util.Iterator;
import  java.util.List;

/**
 * 
 * 
@author  phinecos
 * 
@since  2009-05-22
 *
 
*/
public   class  Test 
{
    
private   static  List < String >  catelogs  =   new  ArrayList < String > ();
    
private   static  List < String >  phrases  =   new  ArrayList < String > ();
    
    
public   static   int  isValidPhrase(String strTested,String strBase)
    {
// 判断此成语是否与基准字符串只差一个字,若是,则返回此索引,否则返回-1
         int  i,count  =   0 ,pos  =   - 1 ;
        
for  (i  =   0 ; i  <  strBase.length();  ++ i)
        {
            
if  (strBase.charAt(i)  !=  strTested.charAt(i))
            {
                
++ count;
                pos 
=  i;
            }
        }
        
if  (count  ==   1 )
        {
// 仅一字之差
             return  pos;
        }
        
else
        {
            
return   - 1 ;
        }
    }
    
public   static   boolean  isSameCatelog( char  chTested, char  chBase)
    {
// 测试两个汉字是否在同一个类别下
         for  (String catelog : catelogs)
        {
            
if  ((catelog.indexOf(chBase)  !=   - 1 &&  (catelog.indexOf(chTested)  !=   - 1 ))
            {
// 两个汉字在同一个类别下
                 return   true ;
            }
        }
        
return   false ;
    }
    
public   static  String correctPhrase(String wrongPhrase)
    {
// 纠正错误
         int  pos;
        Iterator
< String >  iter  =  phrases.iterator();
        
char  chBase,chTested;
        String result 
=   "" ;
        
while  (iter.hasNext())
        {
            String phrase 
=  iter.next(); // 取成语表中当前成语
            pos  =  isValidPhrase(wrongPhrase, phrase);
            
if  ( pos  !=   - 1 )
            {
// 与成语表中当前成语仅一字之差
                chBase  =  phrase.charAt(pos);
                chTested 
=  wrongPhrase.charAt(pos);
                
if  (isSameCatelog(chTested, chBase)  ==   true )
                {
// 在同一个类别下,可以进行修改
                    StringBuilder sb  =   new  StringBuilder(wrongPhrase);
                    sb.setCharAt(pos, chBase);
                    result 
=  sb.toString();
                    
break ;
                }
            }
        }
        
return  result;
    }
    
public   static   void  main(String[] args)  throws  IOException
    {
        
int  n,m,i;
        java.util.Scanner scanner 
=   new  java.util.Scanner(System.in);
        
// 读入n,m,(1<=n<=200,1<=m<=20000)。n表示汉字类别的个数,m表示成语的个数。
        n  =  scanner.nextInt();
        m 
=  scanner.nextInt();
            
        
// 汉字分类表,每个分类中最多包含200个汉字
         for  (i  =   0 ; i  <  n;  ++ i)
        {
            catelogs.add(scanner.next());
        }
        
// 成语列表
         for  (i  =   0 ; i  <  m;  ++ i)
        {
            phrases.add(scanner.next());
        }
        
// 输入待纠错成语
        String wrongPhrase  =  scanner.next();
        
// 输出纠错后成语
        System.out.println(correctPhrase(wrongPhrase));
    }
}

2,公平数

问题背景

如果一个整数的十六进制表示(不含前导0)中,前一半数字之和等于后一半数字之和,我们称它为公平数。

注意,如果该数的十六进制表示中包含奇数个数字,则正中间的数字既不属于前一半,又不属于后一半。

例如在十六进制下1+D=7+7,因此1DE77是公平数。数字E并不参与计算。

再例如,所有单个数字的十六进制数(即0~F)均为公平数,但F0不是(不能把F0补充前导0写成0F0,进而认为它是公平数)。

给出十六进制数 K, X, Y 和十六进制数字集合 S,求区间[X, Y]之内,有多少个公平数满足:

十六进制表达式(不包含前导0)中每个数字均在集合S

并且为K的倍数

输入格式

输入第一行为数字集S,包含0~9以及大写字母A~F

每个数字或字母最多出现一次。

第二行包含 3 个十六进制正整数K, X, Y,均不超过 10 个数字(包含0~9以及大写字母A~F,不包含前导 0)。

输出格式

仅一行,包含一个整数,即满足条件的公平数个数(10进制)。

样例输入

124C

5 100 FFF

样例输出

4

样例解释

只有四个数满足条件:2124244C4C1C

/* ********************************************************************** */
/*  Author: phinecos Date:2009-05-22                                                                      */
/* ********************************************************************** */
#include 
< iostream >
using   namespace  std;

char  s[ 17 ] = { 0 }; // 十六进制数字集合S
long  k,x,y; // 十六进制数X,Y,K

void  charupper( char   * string )
{
    
int  i;

    
for (i = 0 ;i < strlen( string );i ++ )
    {
        
if ( string [i] >= ' a '   &&   string [i] <= ' z ' )
            
string [i]  -= ' a ' - ' A ' ;
    }
}

bool  checksinglechar( char  ch)
{
    
int  i;

    
for (i = 0 ;i < strlen(s);i ++ )
        
if (s[i]  ==  ch)
            
return   true ;

    
return   false ;
}

bool  isAllInSet( long  num)
{
    
char  tstring[ 12 ];
    
int  i;

    sprintf(tstring,
" %lx " ,num);
    charupper(tstring);

    
for (i = 0 ;i < strlen(tstring);i ++ )
    {
        
if (checksinglechar(tstring[i]) == false )
            
return   false ;
    }
    
return   true ;
}

int  convert( char  ch)
{
    
if (ch >= ' a '   &&  ch <= ' f ' )
    {
        
return  (ch - ' a ' + 10 );
    }
    
else   if (ch >= ' A '   &&  ch <= ' F ' )
    {
        
return  (ch - ' A ' + 10 );
    }
    
else   if (ch >= ' 0 '   &&  ch <= ' 9 ' )
    {
        
return  (ch - ' 0 ' );
    }
    
else
        
return   0 ;
}

bool  isFairNum( long  num)
{
// 检查是否是公平数
     char  tstring[ 100 ] = { 0 };
    
int  bsum = 0 ,lsum = 0 ;
    
int  i;

    ltoa(num,tstring,
16 ); // 转换为进制

    
if (strlen(tstring) % 2 == 0 )
    {
// 若长度为偶数,比较前一半数字之和与后一半数字之和
         for (i = 0 ;i < strlen(tstring) / 2 ;i ++ )
            bsum
+= convert(tstring[i]);
        
for (i = strlen(tstring) / 2 ;i < strlen(tstring);i ++ )
            lsum
+= convert(tstring[i]);
        
if (bsum == lsum)
        {
            
return   true ; // 是公平数
        }
        
else
        {
            
return   false ;
        }
    }
    
else
    {
// 若长度为奇数,忽略掉中间的数字
         for (i = 0 ;i < strlen(tstring) / 2 ;i ++ )
            bsum
+= convert(tstring[i]);
        
for (i = strlen(tstring) / 2 + 1 ;i < strlen(tstring);i ++ )
            lsum
+= convert(tstring[i]);
        
if (bsum == lsum)
        {
            
return   true ; // 是公平数
        }
        
else
        {
            
return   false ;
        }
    }
}

int  main()
{
    cin
>> s;
    cin
>> hex >> k >> x >> y;

    
long  nCount  = 0 ; // 符合条件的数字个数

    
for  ( long  num  =  x; num  <=  y;  ++ num)
    {
        
if  ((num % k)  ==   0 )
        {
// 是k的倍数
             if (isFairNum(num)  ==   true )
            {
// 是公平数
                 if (isAllInSet(num)  ==   true )
                {
// 检查十六进制表达式(不包含前导)中每个数字是否均在集合S中
                     ++ nCount;
                }
            }
        }

    }
    cout 
<<  nCount  <<  endl;
    
return   0 ;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Perl编程语言是一种强大的脚本编程语言,适用于各种任务和领域,包括文本处理、系统管理、网络编程等。下面是一个Perl编程的笔试练习题的解答: 题目:编写一个Perl脚本,统计一个文本文件中每个单词出现的次数,并按照频率从高到低的顺序输出。 解答: ```perl #!/usr/bin/perl use strict; use warnings; my $filename = 'text.txt'; open(my $file, "<", $filename) or die "无法打开文件:$!"; my %word_count; while (my $line = <$file>) { chomp($line); my @words = split(' ', $line); foreach my $word (@words) { $word =~ s/[^a-zA-Z]//g; # 只保留字母字符 next if $word eq ''; # 跳过空字符串 $word_count{lc($word)}++; } } close($file); foreach my $word (sort { $word_count{$b} <=> $word_count{$a} } keys %word_count) { print "$word: $word_count{$word}\n"; } ``` 这个Perl脚本首先打开指定的文本文件,并使用`<`操作符将文件内容读入到循环变量`$line`中。在每次迭代中,我们将每一行字符串使用空格进行分割,得到一个单词数组`@words`。接下来,我们使用一个循环遍历`@words`数组中的每个单词,并进行一些处理: 1. 使用正则表达式`s/[^a-zA-Z]//g`去除单词中的非字母字符; 2. 使用`next if $word eq '';`跳过空字符串; 3. 使用`lc($word)`将单词转换为小写字母形式,并将其作为哈希表`%word_count`的键,将该单词的出现次数加一。 在循环结束后,脚本将按照单词出现次数从高到低的顺序对`%word_count`进行排序,并循环打印输出每个单词和其出现次数。 以上是对Perl编程的笔试练习题的参考解答,希望对您有帮助。如果有任何疑问,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值