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.