您必须接受2个字符串输入并输出这两个字符串的总和,而无需将它们转换为int或使用任何数字数据类型。
例如
string one = "123";
string two = "456";
string sum = "579";
假设字符串不能超过10位数字。
这是代码高尔夫,最短的答案是角色获胜。对C#中答案的编辑会使我微笑:)。
编辑:转换为int可以定义为这种性质的任何东西
Int.TryParse
,(int)
,Convert.ToInt
等
您必须接受2个字符串输入并输出这两个字符串的总和,而无需将它们转换为int或使用任何数字数据类型。
例如
string one = "123";
string two = "456";
string sum = "579";
假设字符串不能超过10位数字。
这是代码高尔夫,最短的答案是角色获胜。对C#中答案的编辑会使我微笑:)。
编辑:转换为int可以定义为这种性质的任何东西
Int.TryParse
,(int)
,Convert.ToInt
等
Answers:
53 55 89 E5 8B 4D 0C 8B 55 10 B0 0A 30 DB 88 CF 00 C1 00 C2 49 4A 8A 01 8A 22 00 E0 00 D8 2C 30 30 DB 3C 39 7E 04 B3 01 2C 0A 88 01 88 22 38 CF 75 E2 5D 5B C3
这样就可以从右到左逐位地增加数字,而无需将ascii数字'0'-'9'
转换为整数0-9
,并且可以根据需要进行转换。字节码是函数的代码,可以在C中调用(请参见下文)。
上面的字节码是手工编写的,来自以下程序集(NASM样式,已注释):
; save ebx, ebp
push ebx ; 53
push ebp ; 55
; copy esp
mov ebp, esp ; 8B EC
; load arguments
mov ecx, [ebp+0x0C] ; 8B 4D 0C
mov edx, [ebp+0x10] ; 8B 55 10
; initialize stuff
mov al, 10 ; B0 0A
xor bl, bl ; 30 DB
mov bh, cl ; 88 CF
; send edx, ecx to end of string
add cl, al ; 00 C1
add dl, al ; 00 C2
; decrement everything
dec ecx ; 49
dec edx ; 4A
; get rightmost unprocessed digit of each number
mov al, [ecx] ; 8A 01
mov ah, [edx] ; 8A 22
; add two ascii digits
add al, ah ; 00 E0
; add carry if needed
add al, bl ; 00 D8
; subtract 0x30 ('0') to get the resulting ascii digit
sub al, 0x30 ; 2C 30
; set bl to 0
xor bl, bl ; 30 DB
; if greater than '9': must carry over to next place
cmp al, 0x39 ; 3C 39
jle $+6 ; 7E 04
; set bl to 1 if carrying over
mov bl, 1 ; B3 01
; subtract 10 from ascii digit if carrying over
sub al, 0x0A ; 2C 0A
mov [ecx], al ; 88 01
mov [edx], ah ; 88 22
; check if loop has ended
cmp bh, cl ; 38 CF
jne $-28 ; 75 E2
; restore ebx, ebp
pop ebp ; 5D
pop ebx ; 5B
; return
ret ; C3
要在C(gcc,linux,intel处理器)中尝试此操作:
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
int main(){
// bytecode from earlier
char code[] = {
0x53, 0x55, 0x8B, 0xEC, 0x8B, 0x4D, 0x0C, 0x8B,
0x55, 0x10, 0x31, 0xC0, 0xB0, 0x09, 0x30, 0xDB,
0x01, 0xC1, 0x01, 0xC2, 0x40, 0x50, 0x8A, 0x01,
0x8A, 0x22, 0x00, 0xE0, 0x00, 0xD8, 0x2C, 0x30,
0x30, 0xDB, 0x3C, 0x39, 0x7E, 0x04, 0xB3, 0x01,
0x2C, 0x0A, 0x88, 0x01, 0x88, 0x22, 0x58, 0x48,
0x49, 0x4A, 0x85, 0xC0, 0x75, 0xDF, 0x5D, 0x5B,
0xC3,
};
// allocate executable memory to a function pointer called 'add'
void __attribute__( (__cdecl__) ) (*add)(char*,char*) = mmap(0,sizeof code,PROT_WRITE|PROT_EXEC,MAP_ANON|MAP_PRIVATE,-1,0);
memcpy(add, code, sizeof code);
// test inputs
char number1[] = "0878295272", number2[] = "8184206821";
puts(number1);
puts(number2);
// call the bytecode as a c function
add(number1, number2);
// output is in the first argument
puts(number1);
// release allocated memory
munmap(add, sizeof code);
return 0;
}
俗气。如果你不能把穆罕默德山....
j=$*
r=n=d=0
(d+=x=j.count{|v|n.to_s==v}
r+=x*n
n+=1)until d>1
p r.to_s
算法:
变更日志
71个较短的数组。
85删除了方法声明并合并了对 n.to_s
92应用了一些技巧
101保存字符
102使用x递增
109次初次提交
succ
或prev
....但这对高尔夫来说根本没有意思。
我仍然不确定这是否是Add的dup 而不加(或4个基本算术运算符中的任何一个)。同时,让我交叉发布我对这个问题的答案。它不会赢得任何高尔夫比赛,但它是一个开始,我认为很容易达到规格:
s/([^ ]+) ([^ ]+)/\1:0::\2:/
:d /^([^:]+):\1::([^:]+):/tx
s/(:[^:]*)9([_:])/\1_\2/g;td
s/(:[^:]*)8(_*:)/\19\2/g;s/(:[^:]*)7(_*:)/\18\2/g;s/(:[^:]*)6(_*:)/\17\2/g
s/(:[^:]*)5(_*:)/\16\2/g;s/(:[^:]*)4(_*:)/\15\2/g;s/(:[^:]*)3(_*:)/\14\2/g
s/(:[^:]*)2(_*:)/\13\2/g;s/(:[^:]*)1(_*:)/\12\2/g;s/(:[^:]*)0(_*:)/\11\2/g
s/:(_+:)/:1\1/g; y/_/0/; # #
bd; :x s/.*::([^:]+):/\1/;
# # # # # # # # # # # # # #
输入来自STDIN,格式为“ x y”。首先将其转换为“ x:0 :: y:”。然后,我们将“:”字符后的所有数字递增,直到获得“ x:x::( x + y):”。然后,我们最终返回(x + y)。
$ printf "%s\n" "0 0" "0 1" "1 0" "9 999" "999 9" "12345 67890" "123 1000000000000000000000" | sed -rf add.sed
0
1
1
1008
1008
80235
1000000000000000000123
$
请注意,这仅适用于自然数。但是(至少在理论上)它适用于任意大整数。因为我们在y上执行x递增运算,所以排序可以极大地提高速度:x <y将比x> y快。
y
转换为y+1
仅使用正则表达式吗?没有实际增加吗?真好!
这似乎更符合您在问题中寻找的精神。
它基本上解决了人们在纸上的问题-通过“存储”所有一位数的加法结果,添加每一列,并在必要时了解如何“携带一个”。
这也使用一种“数字数据类型”(变量i),该问题禁止使用它,但仅用于字符串索引。我将尝试删除它并编辑我的答案。
def s p
(y=(?0..?9).to_a).product(y).map{|x|/#{x.join}/}.zip((?0..'18').to_a.each_cons(10).to_a.flatten).each{|k,v|return v if k=~p.sort.join}
end
a,b=$*.map{|n|n.rjust(10,?0).reverse}
r=?0
c=''
(0..9).each{|i|d=s [a[i],b[i]]
c=s([d[-1],r])+c
r=d[-2]||?0}
puts r+c
有点不符合要求:
def s p
y = (?0..?9).to_a
y.product(y).map{ |x|
/#{x.join}/
}.zip(
(?0..'18').to_a.each_cons(10).to_a.flatten
).each{ |k,v|
return v if k =~ p.sort.join
}
end
a,b=$*.map{ |n| n.rjust(10,?0).reverse }
r = ?0
c = ''
(0..9).each { |i|
d = s [ a[i], b[i] ]
c = s([ d[-1], r ]) + c
r = d[-2] || '0'
}
puts r+c
编辑:使用注释中的一些想法来生成“存储的”映射表,而不仅仅是对其进行硬编码。
[?1..?9].zip([?1..?9]).map{|x,y| Regex.new(x+y)}.map{/*something based on the order of results*/}
product
胜过zip
/#{x+y}/
比短Regexp.new(x+y)
。;)
i=-1;(s=(?0..?9).to_a).product(s).map{|x,y|i+=1;/#{x+y}/=>(?0..'18').each_cons(10).to_a[i/10][i%10]}
给你你的正则表达式数组。
i
)...必须有另一种解决方法...也许只是each_cons(10)
用作枚举数并next
遍历该集合?
"Ǻᨌ⹝瀶噄頼籌◳ॶ騥箄덮庸匕帯標ឭ➻䗧㩱砡࣍㤬醻孹꽬"2G#b127b:c~
转化为
lW%'0A*+S/zW%{{A,__m*{_1b\saa*~}%\{_saa*~}%+\aa/,(s_,({(@+\}*}%_Wf<s}g
这肯定可以打很多。我真的不知道我的方法是否最优。
更新 -内联求和矩阵创建以节省字节。因此,该程序现在的运行速度慢了10倍,但是对于任何类型的输入而言,它的运行时间仍然是恒定的。
从STDIN中读取包含两个数字的行作为字符串,并输出为字符串本身的字符数组。
例如:
123 4567
输出包含before 0
。让我知道这是否是一个问题。
感谢Compass,BMac和Shawn提出改进建议。
首先尝试在Code Golf上使用C#似乎是一个障碍...
通过使用,.Compute()
您可以使用字符串值并直接求和。作为奖励,这不仅适用于“ +”,还适用于其他运营商。
打高尔夫球:
static void t(string a,string b){System.Console.Write(new System.Data.DataTable().Compute(a+"+"+b,""));}
取消高尔夫:
static void t(string a, string b)
{
System.Console.Write(new System.Data.DataTable().Compute(a+"+"+b,""));
}
打电话t("123","456");
给您579。
System.Console.WriteLine(new System.Data.DataTable()...
Console.Write
使用与DigitalTrauma解决方案不同的方法。结果,使用O(m + n),该函数的性能甚至更差。将两个操作数都转换为一元,连接,转换回十进制(当然全部使用正则表达式-sed没有整数的概念)。
作为奖励,该程序将stdin(在第一行)中给出的所有自然整数相加,这意味着您可以不输入任何数字,一个数字或十个数字,并且无论做什么,它都会做对的事情。
尽管我不记得它是对哪个问题的解答,但是此代码背后的思想却隐隐地受到了我的旧的PPCG sed提交的启发。
这里是为您的“方便”而打印的“漂亮”,是借用DigitalTrauma的另一个想法。:D
s/9/x8/g;
s/8/x7/g;
s/7/x6/g;
s/6/x5/g;
s/5/x4/g;
s/4/x3/g;
s/3/x2/g;s/2/x1/g;s/1/x0/g;s/0\b//g;;
:l;s/x0/0xxxxxxxxxx/;/x0/bl;s/[^x]//g
s/^$/0/;:m;s/x{10}/!/g;s/!\b/&0/;;;;;
s/0x/1/;s/1x/2/;s/2x/3/;s/3x/4/;;;;;;
s/4x/5/;s/5x/6/;s/6x/7/;s/7x/8/;;;;;;
s/8x/9/;;
s/!/x/g;;
/x{10}/bm
/x/!q;;;;
s/^/0/;bm
#sum.sed#
(要获得266字节的版本,请删除结尾的分号,前导空格和最终注释,最好使用sed。)
从DigitalTrauma借用一些测试:
% printf "%s\n" "0 0" "0 1" "1 0" "9 999" "999 9" "12345 6789" "123 100" | while read l; do sed -rf /tmp/sum.sed <<<"$l"; done
0
1
1
1008
1008
19134
223
由于效率低下,我对大型测试做了一些调整。由于q
仅使用第一行进行处理,因此while
测试中的循环。
在所有荣耀中,Java 都不应该被C#的缺点所超越。这么多样板!用法是提供由空格分隔的参数,即123 456
import javax.script.*;class T {public static void main(String[] a) throws Exception {System.out.print(new ScriptEngineManager().getEngineByName("JavaScript").eval(a[0]+"+"+a[1]));}}
取消高尔夫:
import javax.script.*;
class T {
public static void main(String[] a) throws Exception {
System.out.print(new ScriptEngineManager()
.getEngineByName("JavaScript").eval(a[0] + "+" + a[1]));
}
}
通过使用中提供的JavaScript引擎javax
,我们可以使另一种语言为我们完成工作,并且在技术上遵循不使用本机语言中的任何数字类型或进行转换的规则。
eval
我们尚未将值转换为int,而将JavaScript转换为eval。我们创建了一个"123+456"
不是数字的字符串。JS Engine提取公式并将字符串评估为数字文字,这不是数字数据类型。Java俗气的逻辑!顺便说一句,这也适用于double
数学。
dc -e"$1 $2+p"
技术上我没有在本地bash中使用数字类型一样,它只是将字符串传递给一些实现细节
我认为这属于规则之内。
{⎕D[1+{∨/T←9<Z←0,⍵:∇T↓⍨~×⊃T←(1⌽T)+Z-10×T⋄⍵}+⌿⌽↑⌽¨¯1+⎕D∘⍳¨⍺⍵]}
这个函数需要两个字符串参数,并返回一个字符串:
'123'{⎕D[1+{∨/T←9<Z←0,⍵:∇T↓⍨~×⊃T←(1⌽T)+Z-10×T⋄⍵}+⌿⌽↑⌽¨¯1+⎕D∘⍳¨⍺⍵]}'456'
579
⍝ show dimensions (if it was a number, this would give the empty list)
⍴'123'{⎕D[1+{∨/T←9<Z←0,⍵:∇T↓⍨~×⊃T←(1⌽T)+Z-10×T⋄⍵}+⌿⌽↑⌽¨¯1+⎕D∘⍳¨⍺⍵]}'456'
3
它的速度也相当快,它会立即将999999 9
s 形成的数字加到它自身上。
它找到中的每个字符的索引⎕D
(字符串'0123456789'),然后分别对每个索引进行年级加法,并根据需要携带,然后在中查找结果数字⎕D
。(我认为⎕D
查找符合规则,基本上只是在做'x'-48
)。
说明:
⎕D∘⍳¨⍺⍵
:⎕D
在两个字符串中查找每个字符的索引。¯1+
:1
从每个中减去,因为默认情况下数组是基于1的。⌽↑⌽¨
:将两者都反转,将其转换为矩阵(用零填充空白方块),然后反转矩阵。+⌿
:求和矩阵的各列{
... }
:结转:
∨/T←9<Z←0,⍵
:0
在列表前面添加一个额外的内容。找出哪些“数字”大于9,并将其存储在中T
。如果任何数字大于10:
Z-10×T
:10
从高于10的每个位置减去,T←(1⌽T)+
:将1
每个位置的位置加到大于10的位置旁边,然后存储在中T
。T↓⍨~×⊃T
:如果T
以零开头,请将其删除,∇
:对结果应用进位功能。⋄⍵
:否则,返回值不变1+
:向每个位置添加一个(因为数组是1索引的)⎕D[
... ]
:将结果用作的索引⎕D
。我正在学习Perl,这似乎是一种好习惯。提示,感激不尽!
俗气的答案,以摆脱困境:
print$ARGV[0]+$ARGV[1]; #Adding strings
实际答案:
($x,$y)=@ARGV;while($x.$y.$s){$s-=48-ord$&if$x=~s/.$//;$s-=48-ord$&if$y=~s/.$//;$r=chr($s%10+48).$r;$s=$s>9;}print$r;
未压缩:
($x,$y)=@ARGV;
while($x.$y.$s){
$s-=48-ord$&if$x=~s/.$//;
$s-=48-ord$&if$y=~s/.$//;
$r=chr($s%10+48).$r;
$s=$s>9;
}
print$r;
不使用整数,longs,bytes,shorts,doubles,float或任何内置库函数进行添加。包裹在教室里,打电话给t(String1,String2)
。请使用0填充字符串,使其长度相等。
t("123","234")
返回"0357"
。
打高尔夫球:
char c,d,e,f,g,k;String t(String a,String b){g++;char[]h=a.toCharArray(),i=b.toCharArray(),j=new char[h.length + 1];for(d=(char)h.length;d>f;)j[--d+1]=(c=(e=(char)(h[d]+i[d]-'0'+c))>'9'?g:f)==g?(char)(e-'\n'):e;j[0]=(char)('0'+c);return new String(j);}
高尔夫随着课程的扩展:
public class T{
public static void main(String[] args){
System.out.println(new T().t(args[0],args[1]));
}
char c,d,e,f,g,k;
String t(String a,String b){
g++;
char[]h=a.toCharArray(),i=b.toCharArray(),j=new char[h.length + 1];
for(d=(char)h.length;d>f;)
j[--d+1]=(c=(e=(char)(h[d]+i[d]-'0'+c))>'9'?g:f)==g?(char)(e-'\n'):e;
j[0]=(char)('0'+c);
return new String(j);
}
}
部分打高尔夫球扩大了:
public class TrickSum{
public static void main(String[] args){
System.out.println(new TrickSum().trickSum(args[0], args[1]));
}
char carry, i, aSum,nullChar,oneChar;
public String trickSum(String a, String b){
oneChar++;
char[] number1 = toCharArray(a), number2 = toCharArray(b), sum = new char[number1.length + 1];
for (i = (char) number1.length; i > nullChar;)
sum[--i + 1] = (carry = (aSum = (char) (number1[i] + number2[i] - '0' + carry)) > '9' ? oneChar : nullChar) == oneChar ? (char) (aSum - '\n') : aSum;
sum[0] = (char)('0' + carry);
return new String(sum);
}
char[] toCharArray(String string){
return string.toCharArray();
}
}
100%扩展:
public class TrickSum{
public static void main(String[] args){
System.out.println(trickSum(args[0], args[1]));
}
public static String trickSum(String a, String b){
char[] number1 = a.toCharArray();
char[] number2 = b.toCharArray();
char[] sum = new char[number1.length + 1];
char carry = '\u0000';
for (char i = (char)(number1.length - 1); i != '\uFFFF'; i--){
char aSum = (char) (number1[i] + number2[i] - '0' + carry);
carry = aSum > '9' ? '\u0001' : '\u0000';
aSum = (carry == '\u0001') ? (char) (aSum - '\n') : aSum;
sum[i + 1] = aSum;
}
sum[0] = (char)('0' + carry);
return new String(sum);
}
}
char
是数字数据类型._。
\u0030
为字符串,则"0"
不会"48"
。
众所周知,java没有比Java更好的高尔夫语言了
class A{public static void main(String[]s){char[]a=s[0].toCharArray();char[]b=s[1].toCharArray();int c=a.length;int d=b.length;int e=0;String f="";for(int i=0;i<Math.max(c,d);i++){f=f+(((i<c?a[i]-48:0)+(i<d?b[i]-48:0)+e)%10);e/=10;}System.out.println(f);}}
这是非解决方案
public static void main(String[] args) {
char[] aa = args[0].toCharArray();
char[] bb = args[1].toCharArray();
int aal = aa.length;
int bbl = bb.length;
int reminder = 0;
String result ="";
for(int i=0;i<Math.max(aal,bbl);i++){
result=result+(((i<aal?aa[i]-48:0)+(i<bbl?bb[i]-48:0)+reminder)%10);
reminder/=10;
}
System.out.println(result);
}
f=x=>{for(i=0;i+[]!=x;i++);return i};f((p=prompt)())+f(p())
*这有一些假设:
var a='123',b=321';
版本2(通过用代码初始化字典来缩短):
n={}
for i in range(10):n[`i`]=i*' '
def q(a,b):f=lambda x:''.join([10**p*n[s] for p,s in enumerate(reversed(x))]);return len(f(a)+f(b))
先前版本1(196个字符):
def q(a,b):n,f={0:'','1':' ','2':' ','3':' ','4':4*' ','5':5*' ','6':6*' ','7':7*' ','8':8*' ','9':9*' '}, lambda x:''.join(
[10**p*n[s] for p,s in enumerate(reversed(x))]);return len(f(a)+f(b))
例如
>>> print q('123','111')
234
字典键是字符串,字典值仅包含数字常量以缩短代码,并且计算是通过串联两个字符串并获得结果长度来完成的,因此我希望它算作“不将它们转换为整数”。
class z(int):0
def s(a,b): return z(a)+z(b)
注意:
>>> type(z('4'))
<class '__main__.z'>
类型z是我定义为的自定义类型:无论提问者使用哪种定义,它绝对不是数字类型,但其行为与数字类型足够接近,因此在有限的情况下很有用。z类型的行为仅在此代码示例中部分实现,并且如果CPython解释器使用'int'来实现z,则这仅仅是实现细节,与当前问题无关。