ベース-1 + iの加算


64

ガウス整数a+biaとのb両方の形式の複素数です。ベース-1 + iでは、すべてのガウス整数は、記号を示す記号を必要01せずに、数字とを使用して一意に表現できます。

たとえば1100、基数-1 + iは10進数2を表します。

1*(-1+i)^3 + 1*(-1+i)^2 + 0*(-1+i)^1 + 0*(-1+i)^0
= (2+2i) + (-2i) + 0 + 0
= 2

入力は、数字を使用して表されるベース-1 + iの2つのガウス整数になります01。これは、次のいずれかの形式をとることができます。

  • 2つの個別の数字列、
  • 01基数-1 + iの数値を表す2つの10進整数(1100基数-1 + iの2など)
  • 基数-1 + iの数値を表す2つの2進整数(10進数12または0b1100基数-1 + iの2など)
  • 単一の非英数字セパレーターによって2桁の文字列/バイナリ整数を分離する単一の文字列(1100 1100または12,122 + 2の場合)

2つのガウス整数の合計を、ベース-1 + iで出力し、数字を使用して表されます01(入力として許可される形式の1つで、必ずしも同じ選択ではありません)。出力には、有限数の先行ゼロを含めることができます。

関数またはプログラムは、それぞれ最大30桁の入力に対して2秒以内に終了する必要があります。

追加の説明

  • 入力に余分な先行ゼロが含まれていないと想定できます。0の特殊なケースでは0、表現として空の文字列または空の文字列を選択できます。

テストケース

0, 0 => 0                                      # 0 + 0 = 0
0, 1 => 1                                      # 0 + 1 = 1
1, 1 => 1100                                   # 1 + 1 = 2
1100, 1100 => 111010000                        # 2 + 2 = 4
1101, 1101 => 111011100                        # 3 + 3 = 6
110111001100, 1110011011100 => 0               # 42 + (-42) = 0
11, 111 => 0                                   # i + (-i) = 0
11, 110 => 11101                               # i + (-1-i) = -1
10101, 11011 => 10010                          # (-3-2i) + (-2+3i) = (-5+i)
1010100101, 111101 => 1110100000100            # (-19+2i) + (3-4i) = (-16-2i)

より長いテストケース:

11011011010110101110010001001, 111100010100101001001010010101 => 0
111111111111111111111111111111, 111111111111111111111111111111 => 100100100100100100100100100100
101101110111011101110111011101, 101101110111011101110111011101 => 11101001010001000100010001000100011100
100100010101001101010110101010, 100010011101001011111110101000 => 110000110010101100001100111100010

数字リストはありませんか?
電卓

@CatsAreFluffy数字のリストはありません、ごめんなさい。
Sp3000

96
タイトル-1+ii-1に変更すると、1バイト節約できます。
mbomb007

1
ここで、逆の変換が必要です。:P
Rɪᴋᴇʀ

3
世界には1100種類の人々がいます。バイナリを理解する人、理解しない人、それを三元と混同する人、それをベース4と混同する人、それをベース5と混同する人、それをベース-1 + iと混同する人、それを混同する人ベース6、ベース7と混同する人、ベース8と混同する人、ベース9と混同する人
...-wizzwizz4

回答:


42

Python 2、98 97 91 84バイト

s=input();L=1
for _ in`s`*8:s+=1098*int(str(s).translate('0011'*64));L*=10
print s%L

これは10進数でI / Oを行います。整数は、英数字以外の文字で区切る必要があります+

2バイトのゴルフをしてくれた@xnorに感謝します!

Ideoneで試してみてください。

使い方

複雑な拠点での算術、著者は、フォームのベースに複素数を追加し、乗算する方法を示し-n + I

ベース-1 + iの場合、加算はキャリー付きの通常のバイナリ加算と同様に行われますが、2つの違いがあります。

  • 1を次に高い位置に運ぶ代わりに、110を次の3つの位置に運びます。

  • キャリー桁は無期限に伝播する可能性があります。ただし、先行ゼロがない場合、合計a + bの最大桁数はaおよびbの最大値より8桁多くなります。

次のように進めます。

  1. 最初に、あたかも数字が10進数であるかのようにabを追加ます。

    以下のために= 10101およびB = 11011、これは与え21112

  2. 次に、より大きい数字置き換えることによって、新たな数を形成する11との、他01

    合計21112の場合、これは10001になります。

  3. 1より大きい各桁について、その桁から2を減算し、110を次の上位3 桁まで運ぶ必要があります。以来= 10 * 110 1098から2、我々は、によってステップ2からの結果を乗算することにより、これを達成することができる1098和にその製品を付加し、。2

    合計21112の場合、これは21112 + 1098 * 10001 = 21112 + 10981098 = 11002210になります。

  4. ステップ23を合計d * 8回繰り返します。da + bの桁数です。3

    初期合計21112の結果は次のとおりです。

                          11002210
                          12210010
                        1220010010
                      122000010010
                    12200000010010
                  1220000000010010
                122000000000010010
              12200000000000010010
            1220000000000000010010
          122000000000000000010010
        12200000000000000000010010
      1220000000000000000000010010
    122000000000000000000000010010
                                 .
                                 .
                                 .
    
  5. 10 d + 8を法とする最終合計を取り、最後のd + 8桁を除くすべてを破棄します。

    初期合計21112の場合、最終結果は10010です。


1 これはtranslateで実現さます。文字列0011を 64回繰り返すと、ASCII文字0123のシーケンスと1つの繰り返しラインアップが作成され、目的の置換が行われます。

2 この合計の数字は3(初期値1 + キャリーからの2つの1)を超えてはならないことに注意してください。

3 これは、d = 1で機能し、それ以外の場合はd * 8> d + 8で機能します。コードは、ステップ繰り返すことができる(D + 1)* 8ので、回Sは後続持つLの場合、sはある整数。


7
これは深い魔法です。どのフォーマットがinput()期待されていますか?(21112入力すると取得します10101, 11011。)
ティムペデリック

1
気にしないで; Python 3に翻訳された(失敗したようですが)バージョンを実行していました。Python2でも問題なく動作します
ティムペデリック

9
...どうやって。お願いします。説明してください。
ニックハートリー

@QPaysTaxes回答を編集しました。
デニス

@Dennisでは、なぜそれが機能するのか説明できますか たとえば、なぜですか?d+8たとえば、d+9?どうやって????
ニックハートリー

16

Pyth、34バイト

_shM.u,%J/eMeN\12-+PMeNm.B6/J2k,kQ

オンラインで試してください:デモンストレーションまたはテストスイート(かなり時間がかかります)。オンラインコンパイラは通常の(オフライン)コンパイラと比較して非常に遅いため、時間制限を簡単に満たす必要があります。

説明:

私のアルゴリズムは、基本的にキャリング付き加算の実装です。しかし、その代わりに運んで1、私は実行する必要があり1101100ベースでは-1+i同じである2ベースで-1+i)。これはほとんど問題なく機能しますが、ゼロを出力する無限ループに陥る可能性があります。たとえば、追加111ていて、現在キャリーを持っている場合110。だから、基本的に、ループに陥って停止するまで追加します。ループは常にゼロを出力するため、これは問題ないはずです。

_shM.u,%J/eMeN\12-+PMeNm.B6/J2k,kQ   implicit: Q = input list of strings
                               ,kQ   create the pair ["", Q]
    .u                               modify the pair N (^) until loop:
      ,                                replace N with a new pair containing:
            eN                           N[1] (the remaining summand)
          eM                             take the last digits of each summand
         /    \1                         count the ones
        J                                store the count in J
       %J       2                        J % 2 (this is the first element of the new pair)
                   PMeN                  remove the last digit of each summand
                  +    m   /J2           and add J / 2 new summand:
                        .B6                 with the value "110" (binary of 6)
                 -            k          remove empty summand
    .u                               returns all intermediate results
  hM                                 extract the digits
 s                                   sum them up to a long string
_                                    reverse

13

Python 2、69 67バイト

f=lambda a,b:a*a+b*b^58and 2*f(a*b%2*6,f(a/2,b/2))|a+b&1if a else b

I / Oは、基数2の整数で行われます。

-2ありがとう@Dennis。


私はa*a+b*b^58==0いつaそれbを逆にしますか?それはどのように機能しますか?
xnor

@xnorいいえ、a*a+b*b==58そのうちの1つが3で、もう1つが7の場合。
feersum

1
それ(3,7)がサイクルを与え、特別なケーシングを必要とする唯一のペアであることは私には明らかではありません。それが当てはまる場合、実際(a,b)==(3,7)にその順序でチェックする必要があるのは、に(7,3)再帰するため(3,7)で、おそらくそれに対する短い表現があります。
xnor

1
さて、これは知っている(または忘れる)ない人を混同することが保証されている(a)の^XOR、ない累乗、または(b)のXORがより低い優先順位を持っています+
ティムペデリック

12

網膜、100バイト

r+`(.*)(\d|(?!\4))( .*)(.?)
$2$4:$1$3
T` 0
+`1:11(1*:1*)11
:$1
^:*
:::
}`:(1*:1*:)11
1:1$1
(1)*:
$#1

これは、コンマで区切られた入力を取ります。出力は常に3つの先行ゼロで始まります。

オンラインでお試しください!

最初の段階でもっと短い解決策があるのではないかと本当に思います...


2
いいえ、いいえ、スコアはそのまま完璧です;)
コナーオブライエン

2
-2iの素晴らしいスコア!
ニックハートリー

ワオ。私が私のソリューションを投稿したとき、私はこのソリューションを見ませんでした...私のソリューションよりもはるかに優れています。
リーキー修道女

@KennyLau私はそれを見て、「ええと、私はある時点で説明を追加すべきだったと思います...」
マーティン・エンダー

...- 2i?これは10進数ですが、プログラムはそうでないベースを使用します。
user75200

12

ゼリー、29 28 26 24 21 20バイト

DBḅ1100ḌµDL+8µ¡Dṣ2ṪḌ

これは10進数でI / Oを行います。整数は、英数字以外の文字で区切る必要があります+

オンラインでお試しください!または、すべてのテストケースを確認します

バックグラウンド

複雑な拠点での算術、著者は、フォームのベースに複素数を追加し、乗算する方法を示し-n + I

ベース-1 + iの場合、加算はキャリー付きの通常のバイナリ加算と同様に行われますが、2つの違いがあります。

  • 1を次に高い位置に運ぶ代わりに、110を次の3つの位置に運びます。

  • キャリー桁は無期限に伝播する可能性があります。ただし、先行ゼロがない場合、合計a + bの最大桁数はaおよびbの最大値より8桁多くなります。

次のように進めます。

  1. 最初に、あたかも数字が10進数であるかのようにabを追加ます。

    以下のために= 10101およびB = 11011、これは与え21112

  2. 1より大きい各桁について、その桁から2を減算し、110を次の上位3 桁まで運ぶ必要があります。我々は、バイナリに各進数字を変換することによって、これを達成することができ、ベースから得られたバイナリアレイ1100は整数であり、の結果リスト解釈する0年代、1年代、1100年代と1101非標準塩基として年代を10数。1

    合計21112の場合、これは21112 + 1098 * 10001 = 21112 + 10981098 = 11002210になります。

  3. 手順2を合計d + 8回繰り返します。da + bの桁数です。

    初期合計21112の結果は次のとおりです。

                          11002210
                          12210010
                        1220010010
                      122000010010
                    12200000010010
                  1220000000010010
                122000000000010010
              12200000000000010010
            1220000000000000010010
          122000000000000000010010
        12200000000000000000010010
      1220000000000000000000010010
    122000000000000000000000010010
    
  4. 最終結果から最後のd + 8桁を除くすべてを破棄します。これは、最後の2以降のすべてを破棄することで実現されます。2

    初期合計21112の場合、最終結果は10010です。

使い方

DBḅ1100ḌµDL+8µ¡Dṣ2ṪḌ  Main link. Argument: a + b (implicit sum)

        µ    µ¡       Execute the chain before the first µ n times, where n is
                      the result of executing the chain before the second µ.
         D            Convert a + b to base 10.
          L           Length; count the decimal digits.
           +8         Add 8 to the number of digits.
D                     Convert the initial/previous sum to base 10.
 B                    Convert each digit (0 - 3) to binary.
  ḅ1100               Convert each binary array from base 1100 to integer.
       Ḍ              Interpret the resulting list as a base 10 number.
               D      Convert the final sum to base 10.
                ṣ2    Split at occurrences of 2.
                  Ṫ   Select the last chunk.
                   Ḍ  Convert from base 10 to integer.

1 この合計の桁は3(初期値1 + キャリーからの2つの1)を超えてはならないことに注意してください。

2 これは、キャンセルする最後の数字が3にならないため機能します。


6

Python 3、289バイト

これは、最下位桁から最上位桁への数字ごとの加算(つまり、小学校で教えられたアルゴリズムとまったく同じ)を実行します。違いは、(a)10進数ではなく2進数であるため、数字が2以上の場合は常に持ち運び、(b)1 + 1 = 1100ではありません10

実際には11 + 111 = 0、またはゼロになるはずの合計が終了しないことに注意する必要もあります。

from collections import*
def a(*s,p=0):
 r=defaultdict(int,{0:0})
 for S in s:
  n=0
  for d in S[::-1]:r[n]+=d=='1';n+=1
 while p<=max(r):
  while r[p]>1:
   r[p]-=2
   if r[p+1]>1<=r[p+2]:r[p+1]-=2;r[p+2]-=1
   else:r[p+2]+=1;r[p+3]+=1
  p+=1
 return str([*map(r.get,sorted(r))])[-2::-3]

より多くのゴ​​ルフが確実に可能です。


「ゼロ検出器」で十分だと確信していますか?
ヤック

4
@Yakk:1から査読付きジャーナルまでの規模で、まだ反例はありませんか?
ティムペデリック

2

網膜、157の 151 134 133 124 123バイト

MartinBüttnerに感謝します。

(.+),(.+)
$.1$*0$2,$.2$*0$1,
1
0x
+`(0x*)(,.*)0(x*),
$2,$1$3
{`,

(^|0x0xx0xx)
000
(0x*)(0x*)(0x*0)xx
$1x$2x$3
)`^0+
0
0x
1

オンラインでお試しください!

単項に変換してから、次の置換を繰り返します(ここでは10進数で示します)。

122 -> 000
0002 -> 1100 (this can also be 0012 -> 1110 and 1112 -> 2210 or even 2222 -> 3320 or even 3333 -> 4431)

基本的に、2より大きい場合:2つを取り除いて、前の数字に何も追加せず、前の数字に1つ追加してから、前の数字に1つ追加します。

擬似コードで:

if(a[n]>2):
    a[n] -= 2;
    a[n-2] += 1;
    a[n-3] += 1;

単項実装:

各桁(例3)はxs(例xxx)の数として表示され、接頭辞が付き0ます。

たとえば、1234と表現され0x0xx0xxx0xxxxます。

で表されるように0、これは変更されません。1010x00x

最初は、最終的にはあるので、そこだけある01、変換が簡単で行うことができる1->0x0x->1

すべてのステップを見るにはここをクリックしてください


1

JavaScriptの(ES6)、146の 126バイト

r=n=>n&&n%2-r(n>>=1)-i(n)
i=n=>n&&r(n>>=1)-i(n)
g=(x,y,b=(x^y)&1)=>x|y&&b+2*g(b-x+y>>1,b-x-y>>1)
(x,y)=>g(r(x)+r(y),i(x)+i(y))

gベースにガウス整数(実部と虚部)に変換i-1し、一方r及びi基地変換i-1ガウス整数(それぞれ実部と虚部)に整数。変換が完了したら、算術演算を行うだけです。

編集:実数部と虚数部を別々に計算して20バイトを保存しました。


1

C ++ 416バイト、プラス#include <vector>\n#include <algorithm>\n(別の40)

using I=int;using v=std::vector<I>;void r(v&x){v r{rbegin(x),rend(x)};x=r;}v a(v L,v R){r(L);r(R);L.resize(std::max(L.size(),R.size()));for(int&r:R)L[&r-R.data()]+=r;while(1){L.resize(L.size()+3);auto it=find(rbegin(L),rend(L),2);if(it==rend(L))break;I i=-1+it.base()-begin(L);i&&L[i+1]&&L[i-1]/2?L[i+1]=L[i]=L[i-1]=0:(++L[i+2],++L[i+3],L[i]=0);}L.erase( std::find(rbegin(L),rend(L),1).base(),end(L));r(L);return L;}

または、より多くの空白を使用:

using I=int;
using v=std::vector<I>;

void r(v&x){v r{rbegin(x),rend(x)};x=r;}
v a(v L,v R) {
  r(L);r(R);
  L.resize(std::max(L.size(),R.size()));
  for(int&r:R)
    L[&r-R.data()]+=r;
  while(1) {
    L.resize(L.size()+3);
    auto it=find(rbegin(L), rend(L), 2);
    if(it==rend(L)) break;
    I i=-1+it.base()-begin(L);
    i&&L[i+1]&&L[i-1]/2?
      L[i+1]=L[i]=L[i-1]=0
    :
      (++L[i+2],++L[i+3],L[i]=0);
  }
  L.erase( std::find(rbegin(L),rend(L),1).base(), end(L));
  r(L);
  return L;
}

かろうじてゴルフ。入力をintのベクトルとして受け取り、intのベクトルを返します。

ライブ例

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.