某小朋友写了一段程序,想要打印 99 个'#':
int i, n=99; main() { for(i=0; i<n; i--) { printf("#"); } }
但这显然是不对的。有如下问题:
1.请大家帮他改正, 但只允许 1) 删除一个字符 or 2) 增加一个字符 or 3) 改变一个字符
2.同样的限制条件, 使得只打印一个 '#'
在08-7-3,可可熊 <cocobear.cn@gmail.com> 写道:
某小朋友写了一段程序,想要打印 99 个'#':
int i, n=99; main() { for(i=0; i<n; i--) { printf("#"); } }
但这显然是不对的。有如下问题:
1.请大家帮他改正, 但只允许 1) 删除一个字符 or 2) 增加一个字符 or 3) 改变一个字符
int i, n=99; main() { for(i=0; i<n; i--) { printf("#"); } }
int i, n=99; main() { for(i=0; i<n; n--) { printf("#"); } }
^
2.同样的限制条件, 使得只打印一个 '#'
3.同样的限制条件, 打印 100 个 '#'
可无视所有不合语言规范的东西.. 只要编译通过+答案正确就可以...
============================================================
很有意思啊:D
确实很有意思,想不出来。
From: "可可熊" <cocobear.cn@gmail.com>
Subject: Re: [XiYouLinux] 炎炎夏日,思考道C语言题来消暑
Date: Thu, 3 Jul 2008 14:45:16 +0800
Message-ID: <1babe9be0807022345k44...@mail.gmail.com>
> >
> > 某小朋友写了一段程序,想要打印 99 个'#':
> >
> > int i, n=99; main() { for(i=0; i<n; i--) { printf("#"); } }
> >
> > 但这显然是不对的。有如下问题:
> >
> > 1.请大家帮他改正, 但只允许 1) 删除一个字符 or 2) 增加一个字符 or 3) 改变一个字符
> > 2.同样的限制条件, 使得只打印一个 '#'
>
>
>
>
> int i, n=99; main() { for(i=0; i<n; i--) { printf("#"); } }
> int i, n=99; main() { for(i=0; i<n; i--) ;{ printf("#"); }
> }
> ^
> 这个需要一点解释,(溢出)
>
是啊,还要等一会才出来结果。来,第三题吧^_^,虽然2还有解。
1)
?
2)
int i, n=99; main() { for(i=0; -i<n; i--) { printf("#"); } }
^
3)
int i, n=99; main() { for(i=0; i<n; n--) { printf("#"); } }
^
int i, n=99; main() { for(i=0; i+n; i--) { printf("#"); } }
^
>2.同样的限制条件, 使得只打印一个 '#'
>3.同样的限制条件, 打印 100 个 '#'
>
>可无视所有不合语言规范的东西.. 只要编译通过+答案正确就可以...
>
>============================================================
>很有意思啊:D
>
>--
>Your heart is free, have the courage to follow it.
>I'm vvoody.
>
>>
--
Jianjun Kong | Happy Hacking
HomePage: http://www.kongove.cn
Gtalk: kongj...@gmail.com
On Thu, Jul 03, 2008 at 01:58:43PM +0800, vvoody wrote:
>某小朋友写了一段程序,想要打印 99 个'#':
>
>int i, n=99; main() { for(i=0; i<n; i--) { printf("#"); } }
>
>但这显然是不对的。有如下问题:
>
>1.请大家帮他改正, 但只允许 1) 删除一个字符 or 2) 增加一个字符 or 3) 改变一个字符
1)
?
2)
int i, n=99; main() { for(i=0; -i<n; i--) { printf("#"); } }
^
3)
int i, n=99; main() { for(i=0; i<n; n--) { printf("#"); } }
^
int i, n=99; main() { for(i=0; i+n; i--) { printf("#"); } }
^
不知道你在做什么,哪个是哪个的解?
共三个题,每个题有三种解法 1) 删除一个字符 or 2) 增加一个字符 or 3) 改变
也就是说你刚才只做了 1/9, 后面两个题我正在做……
vvoody,我的理解对吗?
>
> >2.同样的限制条件, 使得只打印一个 '#'
>
> >3.同样的限制条件, 打印 100 个 '#'
> >
> >可无视所有不合语言规范的东西.. 只要编译通过+答案正确就可以...
> >
> >============================================================
> >很有意思啊:D
--
这么主观,题里哪里提到每个问题有三种解法?
这里提到了。
你做的符合第二个要求,增加了一个分号。
> > 1)
> > ?
> >
> > 2)
> >
> > int i, n=99; main() { for(i=0; -i<n; i--) { printf("#"); } }
> >
> > ^
> > 3)
> > int i, n=99; main() { for(i=0; i<n; n--) { printf("#"); } }
> >
> > ^
> > int i, n=99; main() { for(i=0; i+n; i--) { printf("#"); } }
> >
> > ^
> >
> > 不知道你在做什么,哪个是哪个的解?
> >
> >
> > 全打印出来99个。
>
> 那说明我做的是对的,第一题就要求打印99个,而且我采用了规定的两种方法
>
> 共三个题,每个题有三种解法 1) 删除一个字符 or 2) 增加一个字符 or 3) 改变
> 也就是说你刚才只做了 1/9, 后面两个题我正在做……
> vvoody,我的理解对吗?
>
>
> 这么主观,题里哪里提到每个问题有三种解法?
<....>
On Thu, Jul 03, 2008 at 03:25:05PM +0800, 可可熊 wrote:
>
>
>在08-7-3,Jianjun Kong <kongj...@gmail.com> 写道:
>
> On Thu, Jul 03, 2008 at 03:12:55PM +0800, 可可熊 wrote:
> >
> >
> >在08-7-3,Jianjun Kong <kongj...@gmail.com> 写道:
> >
> > On Thu, Jul 03, 2008 at 01:58:43PM +0800, vvoody wrote:
> > >某小朋友写了一段程序,想要打印 99 个'#':
> > >
> > >int i, n=99; main() { for(i=0; i<n; i--) { printf("#"); } }
> > >
> > >但这显然是不对的。有如下问题:
> > >
> > >1.请大家帮他改正, 但只允许 1) 删除一个字符 or 2) 增加一个字符 or 3) 改变一个字符
这里提到了。
你做的符合第二个要求,增加了一个分号。
准确说叫三类解法。这是根据解题的方法(删除/增加/修改一个字符)来分类的,没类可能有多个解(如我给出的用“修改一个字符”打印99#)
>据我所知,第二题的解法目前为止都是一种方法的。
>
>各题的“删除一个字符”想不出来。
--
我想到一个比较“恨”的招数,对于“删除一个字符”的要求,可以把每个字符挨个删除编译,试一遍。当然很明显错误的就不用试了,这个用脚本比较好。
nt i, n=99; main() { for(i=0; i<n; i--) { printf("#"); } }
it i, n=99; main() { for(i=0; i<n; i--) { printf("#"); } }
in i, n=99; main() { for(i=0; i<n; i--) { printf("#"); } }
int , n=99; main() { for(i=0; i<n; i--) { printf("#"); } }
int i n=99; main() { for(i=0; i<n; i--) { printf("#"); } }
int i, =99; main() { for(i=0; i<n; i--) { printf("#"); } }
int i, n99; main() { for(i=0; i<n; i--) { printf("#"); } }
int i, n=9; main() { for(i=0; i<n; i--) { printf("#"); } }
int i, n=9 main() { for(i=0; i<n; i--) { printf("#"); } }
int i, n=99; ain() { for(i=0; i<n; i--) { printf("#"); } }
int i, n=99; min() { for(i=0; i<n; i--) { printf("#"); } }
int i, n=99; man() { for(i=0; i<n; i--) { printf("#"); } }
int i, n=99; mai() { for(i=0; i<n; i--) { printf("#"); } }
int i, n=99; main) { for(i=0; i<n; i--) { printf("#"); } }
……
……
BTW: 请就我和cocobear讨论的问题做题目要求问题,做解答 ;-)
On Thu, Jul 03, 2008 at 03:30:39PM +0800, vvoody wrote:
<....>
>各题的"删除一个字符"想不出来。
我想到一个比较"恨"的招数,对于"删除一个字符"的要求,可以把每个字符挨个删除编译,试一遍。当然很明显错误的就不用试了,这个用脚本比较好。
nt i, n=99; main() { for(i=0; i<n; i--) { printf("#"); } }
it i, n=99; main() { for(i=0; i<n; i--) { printf("#"); } }
in i, n=99; main() { for(i=0; i<n; i--) { printf("#"); } }
int , n=99; main() { for(i=0; i<n; i--) { printf("#"); } }
int i n=99; main() { for(i=0; i<n; i--) { printf("#"); } }
int i, =99; main() { for(i=0; i<n; i--) { printf("#"); } }
int i, n99; main() { for(i=0; i<n; i--) { printf("#"); } }
int i, n=9; main() { for(i=0; i<n; i--) { printf("#"); } }
int i, n=9 main() { for(i=0; i<n; i--) { printf("#"); } }
int i, n=99; ain() { for(i=0; i<n; i--) { printf("#"); } }
int i, n=99; min() { for(i=0; i<n; i--) { printf("#"); } }
int i, n=99; man() { for(i=0; i<n; i--) { printf("#"); } }
int i, n=99; mai() { for(i=0; i<n; i--) { printf("#"); } }
int i, n=99; main) { for(i=0; i<n; i--) { printf("#"); } }
……
……
很有才
BTW: 请就我和cocobear讨论的问题做题目要求问题,做解答 ;-)
这句话好难理解啊
恩,删除用脚本完成是很简单的。现在的问题是,添加和替换如何也用脚本完成??
仔细想想,挺有挑战性的。 :-)
--
Hi, I'm a .signature virus, please copy/paste me to help me spread
all over the world.
int i, n=99; main() { for(i=0; ~ i<n; i--) { printf("#"); } }
^
输出100个。
贡献我的删除脚本:
#!/bin/bash
TEST_VAR='int i,n=99;main(){for(i=0;i<n;i--){printf("#");}}'
i=0
tmpfile=$(mktemp /tmp/test-$$.XXXXXXX)
resultfile=$(mktemp /tmp/test-$$.XXXXXXX)
#echo $resultfile
outfile='/tmp/test_sh.out'
while(($i<${#TEST_VAR}));
do
tmp=${TEST_VAR:0:$i}${TEST_VAR:$((i+1))}
echo $tmp > $tmpfile
gcc -xc -o $outfile $tmpfile &>/dev/null
if [[ $? = 0 ]]
then
echo $tmp
nohup $outfile > $resultfile 2> /dev/null &
sleep 1 && killall $outfile 2> /dev/null
n=$(head -c 101 $resultfile | wc -c)
echo $n
if [ $n = 99 ] || [ $n = 100 ] || [ $n = 1 ]
then
echo $tmp
fi
fi
i=$(($i+1))
done;
貌似删除没答案?我的脚本跑出来没一个符合要求,或者我的脚本哪里错了。:-)
<....>
>恩,删除用脚本完成是很简单的。现在的问题是,添加和替换如何也用脚本完成??
>仔细想想,挺有挑战性的。 :-)
实现了“删除单个字符”,不过没有满足条件的,测试脚本可以把str改成如:
str="pint i, n=99; main() { for(i=0; i+n; i--) { printf(\"#\"); } }"
--------
#!/bin/bash
str="int i, n=99; main() { for(i=0; i+n; i--) { printf(\"#\"); } }"
num=0
check()
{
echo $strr >a.c
rm -f a.out
echo ".......start compiling"
gcc -w a.c -o a.out 2> /dev/null
echo ".......end compiling"
if [ ! -e a.out ]
then
return
fi
n=`./a.out |wc -m`
if [ $n -eq 99 ] || [ $n -eq 1 ] || [ $n -eq 100 ]
then
echo
echo ......the right code
echo $strr
echo ......
echo
echo "It outputs [$n] '#'"
let num=$num+1
fi
}
#main()
charNum=`echo $str |wc -m`
echo $charNum
str[$charNum]=$str
i=0
while [ ! $i -eq $charNum ]
do
let i=$i+1
j=$i+1
#echo ${str:0:$i}${str:$j:$charNum}
strr=${str:0:$i}${str:$j:$charNum}
check
done
echo The right code number is :$num
____________________
增加/修改单个字符,在这个基础上实现也就容易多了
只需要再用一个循环得到一个字符(ASCII码32~126),插入/替换到下面这句
strr=${str:0:$i}${str:$j:$charNum}
我的脚本也发上来了,确实没答案。不过你可以把字符串修改一下,来测试。
TEST_VAR='pint i,n=99;main(){for(i=0;i<n;i--){printf("#");}}'
如果能得到一个正确答案说明你的脚本正确。
这样不行,有几种情况是死循环!你的脚本会卡到这里不动了,因为我的
一开始就是。所以后来我用了nohup和killall。:-)
<snip>
>
>增加/修改单个字符,在这个基础上实现也就容易多了
>
>只需要再用一个循环得到一个字符(ASCII码32~126),插入/替换到下面这句
> strr=${str:0:$i}${str:$j:$charNum}
我觉得这样过于“暴力”了,很多字符还可以再排除!应该结合一下上下文,
不过那样虽快但算法比较复杂。
是的.第三题确实是这样.下面是部分解法.
Q 1:
int i, n=99; main(){ for(i=0; i+n; i--) { printf("#"); } }
int i, n=99; main(){ for(i=0; i<n; n--) { printf("#"); } }
Q 2:
int i, n=99; main(){ for(i=0; i<&n; i--) { printf("#"); } }
int i, n=99; main(){ for(i=0; i<n; i--); { printf("#"); } }
int *i, n=99; main(){ for(i=0; i<n; i--) { printf("#"); } }
int i, *n=99; main(){ for(i=0; i<n; i--) { printf("#"); } }
Q 3:
int i, n=99; main(){ for(i=0; ~i<n; i--) { printf("#"); } }
我的脚本得到8个结果,所有的加起来:
result ==> int *i,n=99;main(){for(i=0;i<n;i--){printf("#");}}
result ==> int i,*n=99;main(){for(i=0;i<n;i--){printf("#");}}
result ==> int i,n=99;main(){for(i=0;-i<n;i--){printf("#");}}
result ==> int i,n=99;main(){for(i=0;~i<n;i--){printf("#");}}
result ==> int i,n=99;main(){for(i=0;i<&n;i--){printf("#");}}
result ==> int*i,n=99;main(){for(i=0;i<n;i--){printf("#");}}
result ==> int i,n=99;main(){for(i=0;i+n;i--){printf("#");}}
result ==> int i,n=99;main(){for(i=0;i<n;n--){printf("#");}}
马上公布脚本。:-)
>增加/修改单个字符,在这个基础上实现也就容易多了
>
>只需要再用一个循环得到一个字符(ASCII码32~126),插入/替换到下面这句
> strr=${str:0:$i}${str:$j:$charNum}
我完成了测试所有结果的脚本。:-)
如下,分两部分,bash部分和perl部分。其实完全可以用perl来完成的。:-)
运行时把它们放到同一个目录中。
Bash脚本:
#!/bin/bash
TEST_VAR='int i,n=99;main(){for(i=0;i<n;i--){printf("#");}}'
#Generated by Python with
#''.join(map(lambda x: '' if chr(x).isupper() else chr(x), range(32, 127)))
#except '$','(',')', '{','}', '[', ']', '@', "\`", "\"", "#", "'", "\\"
possible_chars=' !'"%&*+,-./0123456789:;<=>?^_abcdefghijklmnopqrstuvwxyz|~"
len=${#TEST_VAR}
num_chars=${#possible_chars}
tmpfile=$(mktemp /tmp/test-$$.XXXXXXX)
outfile="/tmp/test_sh.out"
function is_valid_and_ok()
{
echo $1 > $tmpfile
gcc -xc -c -o $outfile.o $tmpfile &>/dev/null
if [[ $? -eq 0 ]]
then
gcc -o $outfile $outfile.o &>/dev/null
if [[ $? -ne 0 ]]; then
return 0
fi
#nohup $outfile > $resultfile 2> /dev/null &
#sleep 1 && killall $outfile 2> /dev/null
n=$(./get_run_result.pl $outfile)
echo $n
if [[ $n -eq 99 ]] || [[ $n -eq 100 ]] || [[ $n -eq 1 ]]
then
return 1
fi
fi
return 0
}
#main
i=0
while(($i<$len - 16));
do
tmp="${TEST_VAR:0:$i}${TEST_VAR:$((i+1))}"
echo "delete: $tmp"
is_valid_and_ok "$tmp"
if [ $? -eq 1 ]
then
echo "result ==> $tmp" 1>&2
fi
i=$(($i+1))
done;
i=4
while(($i < $len - 16));
do
j=0
while(($j<$num_chars));
do
tmp="${TEST_VAR:0:$i}${possible_chars:$j:1}${TEST_VAR:$i}"
echo "add: $tmp"
is_valid_and_ok "$tmp"
if [ $? -eq 1 ]
then
echo "result ==> $tmp" 1>&2
fi
j=$(($j+1))
done
i=$(($i+1))
done;
i=0
while(($i<$len - 16));
do
j=0
while(($j<$num_chars));
do
tmp="${TEST_VAR:0:$i}${possible_chars:$j:1}${TEST_VAR:$((i+1))}"
echo "replace: $tmp"
is_valid_and_ok "$tmp"
if [ $? -eq 1 ]
then
echo "result ==> $tmp" 1>&2
fi
j=$(($j+1))
done
i=$(($i+1))
done;
================================================================
Perl 脚本:
#!/usr/bin/perl -w
use strict;
use warnings;
my $n;
my $chars;
open(my $in_file, "$ARGV[0]|") or exit 1;
$n = read($in_file, $chars, 101);
print "$n\n";
close $in_file;
<....>
>我的脚本得到8个结果,所有的加起来:
>
>result ==> int *i,n=99;main(){for(i=0;i<n;i--){printf("#");}}
>result ==> int i,*n=99;main(){for(i=0;i<n;i--){printf("#");}}
>result ==> int i,n=99;main(){for(i=0;-i<n;i--){printf("#");}}
By_me
>result ==> int i,n=99;main(){for(i=0;~i<n;i--){printf("#");}}
>result ==> int i,n=99;main(){for(i=0;i<&n;i--){printf("#");}}
>result ==> int*i,n=99;main(){for(i=0;i<n;i--){printf("#");}}
>result ==> int i,n=99;main(){for(i=0;i+n;i--){printf("#");}}
By_me
>result ==> int i,n=99;main(){for(i=0;i<n;n--){printf("#");}}
By_me
我做出的3个答案都在上面,cocobear利用溢出,得到的打印1个#的答案脚本没有求出来。
编译:
int i,n=99;main(){for(i=0;i<n;i--);{printf("#");}}
运行可执行文件,得4、5秒才能溢出并打印出一个 #
n=$(./get_run_result.pl $outfile) 用perl脚本判断执行结果时,上面程序还没有运行完。这里没法和死循环区分。
不过cocbear的这个解法太特殊了。
>马上公布脚本。:-)
看到了,很好,很强大!似乎这是一个很好的解题方法,在保证脚本正确的前提下,这样答案更全。
--
Jianjun Kong | Happy Hacking
^^^^^^^^^^^^^
^^^^^^^^^^^^^
恩,看到问题了。不过按理说应该会等待。莫非读是非阻塞的?
我查查看。
不是perl的问题,是我的问题。我人为地排除了cocobear那种可能。。。
下面是修订以后的脚本,得到9个结果。:-)
用时:
real 1m7.964s
user 0m47.115s
sys 0m19.862s
效率上还有不少改进的余地。:-)
=======================================================
#!/bin/bash
i=4
while (($i < $len - 14));
do
j=0
while(($j<$num_chars));
do
tmp="${TEST_VAR:0:$i}${possible_chars:$j:1}${TEST_VAR:$i}"
echo "add: $tmp"
is_valid_and_ok "$tmp"
if [ $? -eq 1 ]
then
echo "result ==> $tmp" 1>&2
fi
j=$(($j+1))
done
i=$(($i+1))
if (($i == 11)) ; then
i=17
fi
done;
i=0
while(($i<$len - 16));
do
j=0
while(($j<$num_chars));
do
tmp="${TEST_VAR:0:$i}${possible_chars:$j:1}${TEST_VAR:$((i+1))}"
echo "replace: $tmp"
is_valid_and_ok "$tmp"
if [ $? -eq 1 ]
then
echo "result ==> $tmp" 1>&2
fi
j=$(($j+1))
done
i=$(($i+1))
if (($i == 11)) ; then
i=17
fi
done;
不是perl的问题,是我的问题。我人为地排除了cocobear那种可能。。。
下面是修订以后的脚本,得到9个结果。:-)
用时:
real 1m7.964s
user 0m47.115s
sys 0m19.862s
echo "" >result.txt
>
>function is_valid_and_ok()
>{
> echo $1 > $tmpfile
> gcc -xc -c -o $outfile.o $tmpfile &>/dev/null
> if [[ $? -eq 0 ]]
> then
> gcc -o $outfile $outfile.o &>/dev/null
> if [[ $? -ne 0 ]]; then
> return 0
> fi
> #nohup $outfile > $resultfile 2> /dev/null &
> #sleep 1 && killall $outfile 2> /dev/null
> n=$(./get_run_result.pl $outfile)
> echo $n
> if [[ $n -eq 99 ]] || [[ $n -eq 100 ]] || [[ $n -eq 1 ]]
> then
> return 1
echo "$n | $tmpfile" >>result.txt
把符合条件的解存入文本,便于查看
> fi
> fi
> return 0
>}
>
>#main
>i=0
这里也可从4开始
跳过“main(){for(” 可以吗?
if (($i == 11)) ; then
i=21
>done;
>
>i=0
这里也可从3开始
>while(($i<$len - 16));
>do
> j=0
> while(($j<$num_chars));
> do
> tmp="${TEST_VAR:0:$i}${possible_chars:$j:1}${TEST_VAR:$((i+1))}"
> echo "replace: $tmp"
> is_valid_and_ok "$tmp"
> if [ $? -eq 1 ]
> then
> echo "result ==> $tmp" 1>&2
> fi
> j=$(($j+1))
> done
> i=$(($i+1))
> if (($i == 11)) ; then
> i=17
> fi
>done;
添加空格带来好多多余值,是否可以考虑把空格从possible_chars中去掉?
如: int i, n=199;main(){for(i=0;i<n;i--){printf("#");}}
--
Jianjun Kong | Happy Hacking
result ==> int i,n=99;main(){for(i=0;i<n;i--);{printf("#");}}
上一个版本的脚本中,在尝试“增加一个字符”时,到倒数第十六个位置时,直接结束,这就把上面的解漏掉了。
while(($i < $len - 16));
^^(最新脚本这里为14)
do
j=0
while(($j<$num_chars));
do
tmp="${TEST_VAR:0:$i}${possible_chars:$j:1}${TEST_VAR:$i}"
echo "add: $tmp"
>
>--
>Free as freedom, slack as Slackware.
>vvoody
>>
--
Jianjun Kong | Happy Hacking
最近的脚本得到9个结果,其中有两个是等价的,所以实际上总共有8个。
:-)
不同意。我更喜欢打印到标准输出,因为我可以直接观察结果。
如果想保存,在外面重定向一次就可以了。
>> fi
>> fi
>> return 0
>>}
>>
>>#main
>>i=0
>
>这里也可从4开始
Agreed.
跳过for有些冒险了吧?不好说~
>>done;
>>
>>i=0
>
>这里也可从3开始
>>while(($i<$len - 16));
>>do
>> j=0
>> while(($j<$num_chars));
>> do
>> tmp="${TEST_VAR:0:$i}${possible_chars:$j:1}${TEST_VAR:$((i+1))}"
>> echo "replace: $tmp"
>> is_valid_and_ok "$tmp"
>> if [ $? -eq 1 ]
>> then
>> echo "result ==> $tmp" 1>&2
>> fi
>> j=$(($j+1))
>> done
>> i=$(($i+1))
>> if (($i == 11)) ; then
>> i=17
>> fi
>>done;
>
>添加空格带来好多多余值,是否可以考虑把空格从possible_chars中去掉?
>如: int i, n=199;main(){for(i=0;i<n;i--){printf("#");}}
恩,对,我本来想着空格可以替换,但那样的话就和删除重复了。
应该可以排除它。
恩,删除用脚本完成是很简单的。现在的问题是,添加和替换如何也用脚本完成??
仔细想想,挺有挑战性的。 :-)
假期实验室照常开放。
请不要在任意主题下回复。