Implementa gli operatori binari di INTERCAL


29

Il linguaggio del compilatore senza acronimo pronunciabile, abbreviato INTERCAL , è un linguaggio di programmazione davvero unico. Tra le sue qualità non riproducibili ci sono i suoi operatori binari.

I due operatori binari di INTERCAL sono interleave (noto anche come mingle ) e selezionano . Interleave è rappresentato con un cambiamento (¢) e select è rappresentato con un sqiggle (~).

Interleave funziona prendendo due numeri nell'intervallo 0-65535 e alternandone i bit. Per esempio:

234 ¢ 4321
234   = 0000011101010
4321  = 1000011100001
Result: 01000000001111110010001001
Output: 16841865

Selezionare le opere prendendo due numeri nell'intervallo 0-65535, prendendo i bit nel primo operando che si trovano nella stessa posizione di 1s nel secondo operando e impacchettando a destra quei bit.

2345 ~ 7245
2345  = 0100100101001
7245  = 1110001001101
Taken : 010   0  10 1
Result: 0100101
Output: 37

In questa sfida, ti verrà data un'espressione binaria usando l'operazione interleave o select. È necessario calcolare il risultato, utilizzando il minor numero possibile di byte.

L'espressione verrà data come una stringa separata da spazio, composta da un numero intero in 0-65535, uno spazio, o ¢o ~, uno spazio e un numero intero in 0-65535.

L'input e l'output possono avvenire attraverso qualsiasi sistema standard (STDIN, funzione, riga di comando, ecc.). Scappatoie standard vietate.

Esempi:

5 ¢ 6
54

5 ~ 6
2

51234 ¢ 60003
4106492941

51234 ~ 60003
422

Questo è il codice golf - vince meno byte. In bocca al lupo.

MODIFICA: poiché alcune lingue non supportano il simbolo di cambio (¢) di INTERCAL, è possibile utilizzare invece il simbolo di denaro grande ($), con una penalità di 5 byte.


10
È un po 'dura penalizzare le persone per l'uso del simbolo del dollaro. Questo è qualcosa che non può essere aiutato.
— Decadimento beta

9
Ho appena capito che CLWNPA è perfettamente pronunciabile in gallese. La W è pronunciata come U in spagnolo o OO in inglese.
— Level River St

9
Non ricevo la penalità di 5 byte. C-INTERCAL utilizza il $.
— Kirbyfan64sos,

13
Di cosa state litigando? Un $ è chiaramente più costoso di un ¢. Cosa, vuoi 99 ¢ per niente?
— Max

6
Non pensavo che INTERCAL ti avrebbe permesso di inserire numeri con numeri decimali. Non devi scrivere FIVE ONE TWO THREE FOUR? E l'output non dovrebbe essere in numeri romani?
— Nate Eldredge,

Risposte:


9

Pyth, 32 31 29 byte

isummFdG}\~zCm.[Z16jvd2%2cz)2

Provalo online: suite di input / test regolari

Grazie a @isaacg per giocare a golf con un byte.

Spiegazione:

                         cz)   split input at spaces
                       %2      only take every second item (the numbers)
             m                 map each number d to:
                    vd           convert d to int
                   j  2          convert to base 2
              .[Z16              pad zeros at the left
            C                  zip
  u     }\~z                   apply the following function ("~" in input) times:
   m   G                         map each pair d to:
    mFd                          convert [x,0] to [] and [x,1] to [x]
 s                             take sum (unfold all lists)
i                           2  convert back from base 2 and print

È possibile salvare un byte cambiando hMfeTper smmFdpoi spostare il duplicato sal di fuori del ternario. Inoltre, il tuo codice attuale è di 32 byte, non di 33.
— isaacg

@isaacg Wow. Non avrei mai pensato a quel golf intelligente. Grazie. E sì, ho fatto un golf all'ultimo minuto mentre scrivevo la spiegazione e non ho aggiornato il conteggio dei byte.
— Jakube,

2
È davvero interessante vedere le risposte di Pyth e CJam, quasi sempre lo stesso numero di byte, ma Pyth spesso batte CJam di pochi
— Kametrixom

13

Python 2, 115 112 byte

x,y,z=input().split()
d=y<""
f=lambda a,b:a+b and(b%2+5&4-d)*f(a/2,b/2)+(a%2*2+b%2)/3**d
print f(int(x),int(z))

La stringa sulla seconda riga contiene un singolo carattere non stampabile \x7d, dopo il carattere successivo ~.

Tutte le speranze di una bella lambda singola vengono schiacciate dal formato di input. C'è probabilmente un modo migliore per leggere in input. Ingresso come "51234 ¢ 60003"tramite STDIN.

La funzione fcombina le seguenti due funzioni ricorsive:

g=lambda a,b:a+b and 4*g(a/2,b/2)+a%2*2+b%2    # ¢
h=lambda a,b:a+b and(b%2+1)*h(a/2,b/2)+a*b%2   # ~

(-3 byte con l'aiuto di @xnor)


1
+1 per la prima risposta Python davvero competitiva. Mi chiedevo perché ti sei preoccupato della lambda e non hai solo usato un'espressione, ma sembra che ci sia qualche ricorsione in là? Non conosco Python, non vedo l'ora di avere una spiegazione.
— Level River St

Qualche bel colpo! Sto cercando di comprimere l'espressione a termine costante. L'espressione (a%2*2+b%2)/3**dsalva 3 caratteri ma usa il complemento d=1-c. Hai un modo di fare -~(3*c|b%2)con il complemento? Nel peggiore dei casi perde 2 caratteri con 3-3*d. Inoltre, il formato and-~x+ypuò andy-~xdurare fino a quando yinizia con un simbolo o un numero.
— xnor

@xnor Capito, (b%2+5&4-d). Grazie!
— Sp3000,

11

CJam, 31 byte

rrc\r]{i2bF0e[}%(7=\zf{_)*?~}2b

Provalo online nell'interprete CJam .

Come funziona

rr                              e# Read two tokens from STDIN.
  c\                            e# Cast the second to char and swap with the first.
    r                           e# Read a third token from STDIN.
     ]                          e# Wrap everything in an array.
      {       }%                e# For all three elements:
       i2b                      e#   Cast to int and convert to base 2.
          F0e[                  e#   Left-pad with zeroes to complete 15 digits.
                (               e# Shift out the first base 2 array.
                 7=             e# Select its eighth MSB (1 for '¢', 0 for '~').
                   \            e# Swap with the array of base 2 arrays.
                    z           e# Zip to transpose rows with columns.
                     f{     }   e# For each pair of base 2 digits:
                                e#   Push the bit, then the pair.
                       _        e#   Copy the pair.
                        )       e#   Pop the second digit.
                         *      e#   Repeat the first digit that many times.
                          ?     e#   Ternary if. Select the pair if the bit is
                                e#    truthy, the repeated first bit if it's falsy.
                           ~    e#   Dump the selected array on the stack.
                             2b e# Convert from base 2 to integer.

8

JavaScript (ES6), 103 117 119 124

modificare ora funziona con i numeri anziché con le stringhe

(senza contare spazi iniziali, nuove righe e commenti)

Prova a eseguire lo snippet su qualsiasi browser compatibile con EcmaScript 6 (in particolare Chrome non MSIE. Ho testato su Firefox, Safari 9 potrebbe andare)

I=s=>
  (i=>{
    for(m=r=0,[a,o,b]=s.split` `;i>0;i<<=1) // loop until bit 31 of i is set
      o>'~'?r+=(b&i)*i+(a&i)*2*i:b&i?r+=(a&i)>>m:++m
  })(1)||r


// TEST
out=x=>O.innerHTML+=x+'\n\n';

[ ['234 ¢ 4321', 16841865], ['2345 ~ 7245', 37]
, ['5 ¢ 6', 54], ['5 ~ 6', 2]
, ['51234 ¢ 60003',4106492941], ['51234 ~ 60003', 422]]
.forEach(([i,o,r=I(i)])=>{
  out('Test '+ (o==r?'OK':'Fail')+'\nInput:    '+ i+'\nResult:   '+r+'\nExpected: '+o)})
<pre id=O></pre>


5

Matlab, 119 113 byte

function f(s)
t=dec2bin(str2double(strsplit(s,{'¢' '~'}))');u=any(s>'~');[~u u]*bin2dec({t(1,t(2,:)==49) t(:)'})

Ungolfed:

function f(s)                                     % input s is a string
t = dec2bin(str2double(strsplit(s,{'¢' '~'}))');  % get the two numbers and convert to
                                                  % two-row char array of zeros of ones
u = any(s>'~');                                   % 1 indicates '¢'; 0 indicates '~'
[~u u]*bin2dec({t(1,t(2,:)==49) t(:)'})           % compute both results and display
                                                  % that indicated by u

Esempi:

>> f('234 ¢ 4321')
ans =
    16841865

>> f('2345 ~ 7245')
ans =
    37

5

R, 145 byte

s=scan(,"");a=as.double(c(s[1],s[3]));i=intToBits;cat(packBits(if(s[2]=="~")c(i(a[1])[i(a[2])>0],i(0))[1:32] else c(rbind(i(a[2]),i(a[1]))),"i"))

Ungolfed + spiegazione:

# Read a string from STDIN and split it on spaces
s <- scan(, "")

# Convert the operands to numeric
a <- as.double(c(s[1], s[3]))

o <- if (s[2] == "~") {
    # Get the bits of the first operand corresponding to ones in
    # the second, right pad with zeros, and truncate to 32 bits
    c(intToBits(a[1])[intToBits(a[2]) == 1], intToBits(0))[1:32]
} else {
    # Interleave the arrays of bits of the operands
    c(rbind(intToBits(a[2]), intToBits(a[1])))
}

# Make an integer from the raw bits and print  it to STDOUT
cat(packBits(o, "integer"))

5

Python 3, 174 166 148 126

Operazioni di stringa piuttosto semplici, quindi conversione in numero intero.

Limitato ai numeri che in binario hanno 99 cifre (max 2 ^ 99-1 = 633825300114114700748351602687).

Grazie, Sp3000 e Vioz!

a,o,b=input().split()
print(int(''.join([(i+j,i[:j>'0'])[o>'~']for i,j in zip(*[bin(int(j))[2:].zfill(99)for j in(a,b)])]),2))

O 165 caratteri, senza limite:

a,o,b=input().split()
a,b=[bin(int(j))[2:]for j in(a,b)]
print(int(''.join([(i if j=='1'else'')if o=='~'else i+j for i,j in zip(a.zfill(len(b)),b.zfill(len(a)))]),2))

Ungolfed:

a, op, b = input().split()
a, b = [bin(int(j))[2:] for j in(a,b)] #convert to int (base 10), then to binary, remove leading '0b'
m = max(len(a), len(b))
a = a.zfill(m) #fill with leading zeroes
b = b.zfill(m)
if op == '~':
    ret = [i if j=='1' else'' for i, j in zip(a, b)]
else:
    ret = [i + j for i, j in zip(a, b)]
ret = ''.join(ret) #convert to string
ret = int(ret, 2) #convert to integer from base 2
print(ret)

2
È possibile utilizzare zfillanziché rjustper il riempimento con zero
— Sp3000

Ingressi max out a 16 bit e output a 32 bit. 99 bit è più che sufficiente.
— Isaacg,

Lo so, ma dal momento che "99" accetta tanti caratteri quanti ne "16", non c'è alcun vantaggio nel limitarlo.
— Trang Oul,

1
Qualche altro in più: 1) Non è necessario salvare a,b, basta inserirlo zipcon un *simbolo, 2) (i if j=='1'else'') -> i[:j>'0']3) È possibile utilizzare questo suggerimento per salvare sull'altroif/else
— Sp3000

1
La mia soluzione finì per essere troppo vicina alla tua, quindi ecco quanto potevo ottenere la tua (126 byte).
— Kade,

4

Pyth, 43 byte

Una parte di me si sente nervosa nel pubblicare una risposta Pyth così lunga sulla domanda di isaacg ...: oP

J.(Kczd1Am.BvdKiu?qJ\~u+G?qeH\1hHk+VGHk.iGH2

spiegazione:

                                               Implicit: z=input(), k='', d=' '
   Kczd                                        Split z on spaces, store in K
J.(    1                                       Remove centre element from K, store in J
         m    K                                For each d in K
          .Bvd                                 Evaluate as int, convert to binary string
        A                                      Store pair in G and H
                                               ~ processing:
                                 +VGH          Create vectorised pairs ([101, 110] -> [11, 01, 10])
                     u               k         Reduce this series, starting with empty string
                        ?qeH\1                 If 2nd digit == 1...
                              hHk              ... take the 1st digit, otherwise take ''
                      +G                       Concatenate
                                      .iGH     ¢ processing: interleave G with H
                ?qJ\~                          If J == ~, take ~ processing, otherwise take ¢
               i                          2    Convert from binary to decimal

4
Adoro la foto del tuo profilo! :)
— kirbyfan64sos

2
@ kirbyfan64sos Blue Kirby è il migliore Kirby: o)
— Prese l'

3

C, 127 123 byte + 5 penalità = 128

scanfconta il simbolo unicode come più di un carattere che complica molto le cose, quindi sto applicando la penalità di 5 byte per l'utilizzo $.

a,b,q,x,i;main(){scanf("%d %c %d",&a,&q,&b);for(i=65536;i/=2;)q%7?x=x*4|a/i*2&2|b/i&1:b/i&1&&(x=x*2|a/i&1);printf("%u",x);}

Le modifiche rispetto alla versione originale sono:

-Il test per $ o ~ è stato rivisto da q&2a q%7. Ciò inverte i valori vero / falso, consentendo al codice per l'operatore $ di precedere il :che significa che è possibile eliminare un set di parentesi.

-Il iloop ora conta alla rovescia in potenze di 2 che sono più lunghe, ma che >>possono essere sostituite da/ e salva alcune parentesi.

Versione originale 127 byte

a,b,q,x,i;
main(){
  scanf("%d %c %d",&a,&q,&b);
  for(i=16;i--;)
    q&2?
      b>>i&1&&(x=x*2|a>>i&1):    // ~ operator. && used as conditional: code after it is executed only if code before returns truthy.
      (x=x*4|(a>>i&1)*2|b>>i&1); // $ operator
  printf("%u",x);
}

Sono andato con un singolo anello con i condizionali all'interno per evitare il sovraccarico di due anelli. In entrambi i casi sposto i bit degli operandi fino ai bit 1 e costruisco il risultato dal bit più significativo a quello meno significativo, spostando a sinistra il risultato (moltiplicando per 2 o 4) mentre procedo.


L'ho giocato per te: main (a, b, q, x, i) {scanf ("% d% c% d", & a, & q, & b); for (i = 16; i -;) q & 2? b >> i & 1 && (x = x * 2 | a >> i & 1) :( x = x * 4 | (un >> i & 1) * 2 | b >> i & 1); printf ( "% u", x);} Ho provato a golf via le parti >> i & 1, ma non sono riuscito a trovare un modo economico per farlo. Sono stato in grado di salvare 1 carattere tuttavia mettendo le definizioni delle variabili in principale. Nota: non testato.
— LambdaBeta,

@LamdaBeta grazie, non sono riuscito a trovare una macro per >> i & 1 ma sono riuscito a giocare a golf in un altro modo. Mettere le variabili come argomenti di maincause qda corrompere sulla mia macchina, il che è strano. Mi aspetto che il vero problema siascanf , ma per questo li ho lasciati come normali dichiarazioni.
— Level River St

Non ci avevo pensato. Hai ragione, q sarà danneggiato. Il motivo è che mentre apprendiamo che main accetta due argomenti, il conteggio degli argomenti della riga di comando e una matrice degli argomenti stessi, la maggior parte dei sistemi in realtà fornisce un terzo argomento (in genere chiamato char * envp []) che descrive l'ambiente il codice viene eseguito (garantendo l'accesso a EG: variabili di ambiente). Quindi al terzo valore in main può anche essere assegnato un valore dal sistema, scanf è innocente questa volta.
— LambdaBeta,

@steveverill Penso che puoi anche rimuovere la penalità di 5 byte. Ho appena testato il tuo codice (usando ALT + 155 per creare ¢) e sembra funzionare bene. :)
— LambdaBeta,

@LambdaBeta in realtà la sperimentazione mostra che è una combinazione di entrambi. Con la dichiarazione normale qè garantito essere zero, ma con la dichiarazione come parametro di funzione qcontiene immondizia a 32 bit. Non sarebbe un problema se assegnassi un valore a q, ma scanfcon "%c"solo sovrascrivo gli 8 bit meno significativi della spazzatura, lasciando gli altri 24 indefiniti. Potrei essere fortunato su un altro compilatore!
— Level River St

3

K5, 53 52 byte

{b/({,/x,'y};{x@&y})[*"~"=y][b\.x;(b:20#2)\.z]}." "\

Versione a 53 byte:

{b/({,/x,'y};{x@&y})[*"¢~"?y][b\.x;(b:20#2)\.z]}." "\

Ha ancora bisogno di un po 'più di golf.



3

Haskell, 77

g=(`mod`2)
h=(`div`2)
0¢0=0
a¢b=g a+2*b¢h a
a?0=0
a?b=g a*g b+(1+g b)*h a?h b

l'input viene dato applicando l'input alle funzioni / operatori ?e ¢definito nel codice (Haskell non può definire un operatore~ per motivi tecnici).

fondamentalmente funziona il vecchio approccio ricorsivo.


2

J, 173

f=:|."1@(>@(|.&.>)@(#:@{:;#:@{.))
m=:2&#.@:,@:|:@:|.@:f
s=:2&#.@#/@:f
a=:{&a.@-.
(1!:2)&2(s@".@:a&126)^:(126 e.i)((m@".@:a&194 162)^:(1 e.194 162 E.i)i=._1}.(a.i.((1!:1)3)))

si aspetta una riga di input

input previsto per terminare dopo la nuova riga con EOF


2

Javascript ES6 (3 argomenti) 141 138 136 121 119 byte

b=x=>(65536|x).toString`2`
f=(x,o,y)=>+eval(`'0b'+(b(y)+b(x)).replace(/^1|${o=='~'?1:'(.)'}(?=.{16}(.)())|./g,'$2$1')`)

Test:

;[f(234,'¢',4321),f(2345,'~',7245)]=="16841865,37"

Javascript ES6 (1 argomento) 135 133 byte

b=x=>(65536|x).toString`2`
f=s=>([x,o,y]=s.split` `)|eval(`'0b'+(b(y)+b(x)).replace(/^1|${o=='~'?1:'(.)'}(?=.{16}(.)())|./g,'$2$1')`)

Test:

;[f('234 ¢ 4321'),f('2345 ~ 7245')]=="16841865,37"

PS: la nuova riga viene conteggiata come 1 byte in quanto può essere sostituita da ;.


1
0x10000 == 65536 (salva 2 caratteri)
— edc65

@ edc65, ho aggiornato la risposta.
— Qwertiy,

2
65536 | x per evitare ~~
— edc65

È consentita solo la seconda versione: l'input deve essere nella forma di una stringa delimitata da spazi.
— Isaacg,

@isaacg, ok. Ma non voglio cancellare il primo per motivi storici.
— Qwertiy,

2

Python 3, 157 byte

a,x,y=input().split()
i=int
b=bin
print(i(''.join(([c for c,d in zip(b(i(a)),b(i(y)))if d=='1'],[c+d for c,d in zip(b(i(a))[2:],b(i(y))[2:])])['¢'==x]),2))

La versione completa ed esplicativa può essere trovata sul mio pastebin .


Puoi fare lo stesso con alcuni caratteri rimuovendo gli spazi intorno all'operatore '==', prima di 'if' e passando 'base' come argomento posizionale.
— Trang Oul,

Grazie, questo e alcuni altri hanno risparmiato 15 caratteri! ma il modo raddoppiato di formattare il ritorno è ancora molto.
— Oliver Friedrich,

Inoltre, usi 4 spazi per trattino? Uno (o una scheda) è sufficiente.
— Trang Oul,

2
@BeowulfOF Se non diversamente specificato, è possibile inviare un programma completo o una funzione. Generalmente, ciò che è più breve dipenderà dal modo in cui la tua lingua analizza l'input specifico per la sfida (ruby è sorprendentemente goffo con numeri dallo stdin per esempio). Esistono anche due modi possibili di output: stdout o valore di ritorno, che sono applicabili ad entrambi (sebbene i valori di ritorno dai programmi siano rari).
— Level River St

1
Sembra che utilizzi euna sola volta, non puoi semplicemente inserirlo?
— Kevin Brown,

0

Mathematica, 155 byte

f=IntegerDigits[#,2,16]&;
g=#~FromDigits~2&;
¢=g[f@#~Riffle~f@#2]&;
s=g@Cases[Thread@{f@#,f@#2},{x_,1}->x]&;
ToExpression@StringReplace[#,{" "->"~","~"->"s"}]&

Valuta una funzione anonima che accetta la stringa come input. Le interruzioni di riga sono state aggiunte per maggiore chiarezza.

fe gconverti in / dalla base 2. Rifflefa esattamente ciò che si suppone interleave . Volevo usare Selectper selezionare ma Casessfortunatamente è meglio. L'ultima riga è un po 'ingannevole; gli spazi vengono cambiati in ~quale è l'operatore infix di Mathematica, quindi viene valutata la stringa.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.