Dividi un numero per 3 senza usare gli operatori *, /, +, -,%


48

Citando questa domanda su SO (Spoiler alert!):

Questa domanda è stata posta in un'intervista a Oracle.

Come divideresti un numero per 3 senza usare *, /, +, -,%, operatori?

Il numero può essere firmato o non firmato.

L'attività è risolvibile, ma controlla se riesci a scrivere il codice più breve.

Regole:

  • Esegue la divisione intera richiesta ( /3)
  • Non utilizzare gli operatori non-text-based *, /, +, -, o %(o loro equivalenti, come ad esempio __div__o add()). Questo vale anche per gli operatori di incremento e decremento, come i++o i--. L'uso degli operatori per la concatenazione e la formattazione delle stringhe è OK. L'uso di questi caratteri per operatori diversi, come un -operatore unario per numeri negativi, o *per rappresentare un puntatore in C è anch'esso OK.
  • Il valore di input può essere arbitrariamente grande (qualunque cosa il tuo sistema sia in grado di gestire), sia positivo che negativo
  • L'ingresso può essere su STDIN o ARGV o inserito in altro modo
  • Crea il codice più corto possibile per fare quanto sopra

1
Come dovrebbe essere arrotondato il risultato se positivo? Come quando negativo?
dfeuer

Risposte:


15

J, 45 44 10 caratteri

".,&'r3'":

Funziona con negativi:

".,&'r3'": 15
5
   ".,&'r3'": _9
_3
   ".,&'r3'": 3e99
1e99

": - formatta come testo

,&'r3'- Aggiungi r3alla fine

". - esegue la stringa, ad es 15r3


1
Funziona se lo fai 3 3 3 #: 9. Sembra che tu debba sapere quanto tempo sarà il tuo numero ternario. _3]\i.è anche un possibile punto di partenza per qualcosa, ma non so se sarebbe più breve della tua soluzione qui. Il problema #_3]\i.così com'è è che arrotonda sempre anziché verso il basso.
Gareth,

1
Forse ##~3=_3#\i.per 11 personaggi?
Gareth,

1
In realtà, puoi ridurre i tuoi fino a 10 caratteri con ##~0 0 1$~.
Gareth,

1
Puoi ridurlo usando un hook 3#.}:(#:~$&3)ma è ancora più lungo e non risolve il problema del numero negativo.
Gareth,

1
Sì, è possibile utilizzare la funzione di alimentazione ^: o l' agenda @. per una ifo una if...elsesostituzione. In questo caso potresti essere in grado di usare @.due verbi collegati con un carattere '' (un gerundio in J-speak) per selezionare l'uno o l'altro in base a una condizione.
Gareth,

56

C, 167503724710

Ecco la mia soluzione al problema. Devo ammettere che è improbabile che vinca una competizione di golf in codice rigoroso, ma non usa alcun trucco per chiamare indirettamente la funzionalità di divisione integrata, è scritto in C portatile (come richiesto dalla domanda originale Stack Overflow), funziona perfettamente per i numeri negativi e il codice è eccezionalmente chiaro ed esplicito.

Il mio programma è l' output del seguente script:

#!/usr/bin/env python3
import sys

# 71
sys.stdout.write('''#include <stdint.h>
#include <stdio.h>
int32_t div_by_3(int32_t input){''')

# 39 * 2**32
for i in range(-2**31, 2**31):
    # 18 + 11 + 10 = 39
    sys.stdout.write('if(input==%11d)return%10d;' % (i, i / 3))

# 95
sys.stdout.write(r'''return 7;}int main(int c,char**v){int32_t n=atoi(a[1]);printf("%d / 3 = %d\n",n, div_by_3(n));}''')

Numero di caratteri: 71 + 39 * 2 ** 32 + 95 = 167503724710

benchmark

È stato chiesto quanto tempo ci vorrebbe e quanta memoria avrebbe usato, quindi ecco alcuni parametri di riferimento:

  • Tempo di esecuzione dello script: l'esecuzione ./test.py | pv --buffer-size=1M --average-rate > /dev/nullper circa 30 secondi fornisce una velocità di circa 14,8 MB / s. Si può ragionevolmente supporre che la velocità di uscita sia approssimativamente costante, quindi il tempo di esecuzione fino al completamento dovrebbe essere circa 167503724710 B / (14,8 * 1048576 B / s) ≈ 10794 s.
  • Tempo di compilazione - Il compilatore TCC afferma di compilare il codice C a 29,6 MB / s , il che comporta un tempo di compilazione di 167503724710 B / (29,6 * 1048576 B / s) ≈ 5397 s. (Naturalmente questo può essere eseguito in una pipeline con lo script.)
  • Dimensione del codice compilato: ho provato a stimarlo usando ./test.py | tcc -c - -o /dev/stdout | pv --buffer-size=1M --average-rate > /dev/null, ma sembra tccche non produca nulla fino a quando non legge l'intero file sorgente.
  • Utilizzo della memoria da eseguire: poiché l'algoritmo è lineare (e tcc non si ottimizza su più righe), l'overhead della memoria dovrebbe essere solo di pochi kilobyte (a parte il codice stesso, ovviamente).

22
Questo è l'epitome di hardcoding. ++++++++++
Joe Z.

4
Detto questo, sono sicuro che se hai dato loro un file sorgente da 160 GB e hai chiesto loro di compilarlo e testarlo, ti guarderebbero come se fossi pazzo.
Joe Z.

16
Se il mio capo mi chiedesse di calcolare una divisione per tre senza - + / *% penserei che sia pazzo.
Mikaël Mayer

Eppure, a[b]è uno zucchero sintattico per *(a + b), che fa l'aggiunta.
Konrad Borowski il

12
@NicolasBarbulesco Esiste una limitazione di dimensione sulle risposte di Stack Exchange.
Timtech,

38

Ruby 28

b=->n{n.to_s(3).chop.to_i 3}

Per dividere per 3 dobbiamo solo rimuovere lo zero finale nel numero di base 3: 120 -> 11110 -> 1111 -> 40

Funziona con negativi:

ice distantstar:~/virt/golf [349:1]% ruby ./div3.rb
666
222
ice distantstar:~/virt/golf [349]% ruby ./div3.rb
-15        
-5

Ruby, 60 45

In alternativa, senza usare la conversione di base:

d = -> n {x = n.abs; r = (0..1.0 / 0) .step (3) .take (x) .index x; n> 0? r: -r}

d=->n{(r=1.step(n.abs,3).to_a.size);n>0?r:-r}

1
L'alternativa senza conversione di base ha l' /operatore vietato dove è Float::INFINITYdiventato 1.0/0. Con Ruby 2.1, si può giocare (0..1.0/0).step(3)a golf 0.step(p,3), rimuovendo il /. Il problema più grande è che -rusa -per negare. Il costo è di 5 caratteri di cambiare -ra ~r.pred, abusando Integer # pred per sottrarre 1 senza che l'operatore di sottrazione.
kernigh,

26

Mathematica, 13 caratteri

Mean@{#,0,0}&

Questo è malvagio: DI suppongo che tu possa salvare la &e usare una semplice variabile (anche altri lo fanno qui).
Yves Klett,

3
@YvesKlett: Mean è intrinsecamente malvagio.
GuitarPicker

18

JavaScript, 56

alert(Array(-~prompt()).join().replace(/,,,/g,1).length)

Fa una stringa di lunghezza ndi ripetizione ,s e sostituisce ,,,con 1. Quindi, misura la lunghezza risultante della stringa. (Speriamo che sia unario -permesso!)


+1 ma non funziona con valori negativi
Francesco Casula

Uh, domanda ... come conta questo? Utilizza l' -operatore di negazione.
Patrick Roberts,

@Patrick Ho preso la specifica per significare nessuna sottrazione - se vuoi, puoi sostituirla -~conparseInt()
Casey Chu

@CaseyChu il valore restituito da -~prompt()è uno maggiore di parseInt(prompt()). Non sono sicuro di come lo faresti.
Patrick Roberts,

alert(Array(parseInt(prompt())).slice(1).join().replace(/,,,/g,1).length)
Casey Chu,

16

Python, 41 38

print"-"[x:]+`len(xrange(2,abs(x),3))`

xrange sembra essere in grado di gestire grandi numeri (penso che il limite sia lo stesso di un lungo in C) quasi istantaneamente.

>>> x = -72
-24

>>> x = 9223372036854775806
3074457345618258602

2
10/3è uguale a 3, non a 4.
Joel Cornett

Doing print" -"[x<0]+len (range (2, abs (x), 3)) `` lo raderà fino a 39 caratteri
Joel Cornett

La formattazione dei commenti di golfexchange lo sta rovinando. sopra ho usato i bastoncini da racchiudere len()come abbreviazione direpr()
Joel Cornett il

L'ho aggiornato. Non posso usare range, perché in realtà creerà l'elenco. xrangefa solo finta di essere, quindi è in grado di gestire enormi numeri senza perdere tempo / memoria.
GRC

2
Fai finta che sia Python 3;) Mi piace il singolo carattere che taglia tra l'altro.
Joel Cornett,

11

Haskell, 90 106

d n=snd.head.dropWhile((/=n).fst)$zip([0..]>>=ν)([0..]>>=replicate 3>>=ν);ν q=[negate q,q]

Crea un elenco di ricerca infinito (pigro) [(0,0),(0,0),(-1,0),(1,0),(-2,0),(2,0),(-3,-1),(3,1), ...], taglia tutti gli elementi che non corrispondono n( /=è la disuguaglianza in Haskell) e restituisce il primo che lo fa.

Questo diventa molto più semplice se non ci sono numeri negativi:

25 27

(([0..]>>=replicate 3)!!)

restituisce semplicemente l' nelemento th dell'elenco [0,0,0,1,1,1,2, ...].


3
oO non ho mai pensato a quella seconda soluzione. Potrei essere in grado di implementare qualcosa del genere in Python
Accolito il

8

C #, 232 byte

Il mio primo codice golf ... E poiché non esisteva C # e volevo provare un metodo diverso non provato qui, ho pensato di provarlo. Come alcuni altri qui, solo numeri non negativi.

class l:System.Collections.Generic.List<int>{}class p{static void Main(string[] g){int n=int.Parse(g[0]);l b,a=new l();b=new l();while(a.Count<n)a.Add(1);while(a.Count>2){a.RemoveRange(0,3);b.Add(1);}System.Console.Write(b.Count);}}

Ungolfed

class l : System.Collections.Generic.List<int>
{ }
class p
{
    static void Main(string[] g)
    {
        int n = int.Parse(g[0]);
        l b, a = new l();
        b = new l();
        while (a.Count < n) a.Add(1);
        while (a.Count > 2)
        {
            a.RemoveRange(0, 3);
            b.Add(1);
        }
        System.Console.Write(b.Count);
    }
}

2
Circa 5 anni dopo .. È possibile salvare 1 byte rimuovendo lo spazio da string[] g, trasformandolo instring[]g
Metoniem

Citando "Non usare gli operatori non testuali *, /, +, - o% (o i loro equivalenti, come div o add ()" - non stai usando un equivalente - .Add?
Jonathan Frech

@JonathanFrech Quel metodo di aggiunta non funziona su due numeri, aggiunge solo un valore a una raccolta
Incarnazione dell'ignoranza

7

Perl (26 22)

$_=3x pop;say s|333||g

Questa versione (ab) utilizza il motore regex di Perl. Legge un numero come ultimo argomento della riga di comando ( pop) e crea una stringa di 3s di questa lunghezza ( "3" x $number). L'operatore di sostituzione regex ( s///, qui scritto con delimitatori diversi a causa delle regole del puzzle e con una gbandiera lobal) sostituisce tre caratteri con la stringa vuota e restituisce il numero di sostituzioni, che è il numero di input intero diviso per tre. Potrebbe anche essere scritto senza 3, ma la versione sopra sembra più divertente.

$ perl -E '$_=3x pop;say s|333||g' 42
14

2
Ehi @memowe, bel lavoro! Facendo potresti risparmiare qualche altro carattere (4) $_=3x pop;say s|333||g.
Dom Hastings,

2
Quando l'input è 0, 1 o 2, stampa una stringa vuota. Se ha bisogno di stampare 0, quindi ha bisogno di più di 3 caratteri (25 totale): '$_=3x pop;say s|333||g||0. Lento con numeri grandi come 99999999 e non funziona con numeri negativi.
kernigh,

1
Usalo -psulla riga di comando e puoi fare: $_=3x$_;$_=0|s|...||gper un totale di 22, inclusa la copertura degli ingressi 0, 1 o 2.
Xcali,

6

C, 160 caratteri

Soluzione di divisione lunga carattere per carattere usando le tabelle di ricerca, cioè senza stringa atoi () o printf () per convertire tra 10 stringhe di base e numeri interi.

L'output a volte includerà uno zero iniziale - parte del suo fascino.

main(int n,char**a){
char*s=a[1],*x=0;
if(*s==45)s=&s[1];
for(;*s;s=&s[1])n=&x[*s&15],x="036"[(int)x],*s=&x["000111222333"[n]&3],x="012012012012"[n]&3;
puts(a[1]);
}

Nota:

  • abusa dell'accesso all'array per implementare l'aggiunta.
  • viene compilato con clang 4.0, altri compilatori potrebbero non essere validi.

test:

./a.out -6            -2
./a.out -5            -1
./a.out -4            -1
./a.out -3            -1
./a.out -2            -0
./a.out -1            -0
./a.out 0             0
./a.out 1             0
./a.out 2             0
./a.out 3             1
./a.out 4             1
./a.out 5             1
./a.out 6             2
./a.out 42            14
./a.out 2011          0670

6

Python 42

int(' -'[x<0]+str(len(range(2,abs(x),3))))

Dal momento che ogni soluzione pubblicata qui che ho controllato tronca i decimali qui è la mia soluzione che lo fa.

Python 50 51

int(' -'[x<0]+str(len(range([2,0][x<0],abs(x),3))))

Dal momento che Python fa la divisione del pavimento, ecco la mia soluzione che lo implementa.

L'intero di input è nella variabile x.

Testato in Python 2.7 ma sospetto che funzioni anche in 3.


+1 Per offrire entrambe le alternative alla situazione di valore negativo. Dato che ci sono già così tante risposte, non aggiusterò le specifiche per escludere l'una o l'altra opzione, anche se sarei personalmente d'accordo sul fatto che -3sia la risposta corretta -10/3.
Gaffi,

Per coloro a cui interessa la divisione dei piani in Python: python-history.blogspot.com/2010/08/…
Matt

cosa succede con la moltiplicazione e la sottrazione nella tua seconda soluzione?
stand

@boothby La seconda soluzione implementa la divisione del pavimento. Volevo fare range (0, abs (x), 3) per numeri negativi e range (2, abs (x), 3) per numeri positivi. Per fare ciò avevo un intervallo (2 ... poi ho sottratto 2 quando x è negativo. X <0 è vero quando x è negativo, (vero) * 2 == 2
Matt

Non capisco la differenza tra divisione del pavimento e decimali troncati. Questo ha a che fare con una divisione negativa?
Joel Cornett,

6

JavaScript, 55

alert(parseInt((~~prompt()).toString(3).slice(0,-1),3))

Se uno non può usare -1, allora ecco una versione che lo sostituisce con ~0(grazie Peter Taylor!).

alert(parseInt((~~prompt()).toString(3).slice(0,~0),3))

1
@ArtemIce One ~è un operatore Bitwise che inverte i bit dell'operando (convertendolo prima in un numero). Questo è il modo più breve per convertire una stringa in un numero (per quanto ne so).
Inkbug

1
Sento che usare l'analisi delle stringhe / la conversione è un imbroglio, dal momento che a) un processo molto complicato e costoso rispetto alle operazioni bit a bit, b) utilizza internamente gli operatori proibiti, e c) occuperebbe waaaaay più caratteri di una soluzione homerolled. Un po 'come il modo in cui le persone diventano scontrose quando usi i tipi integrati quando ti viene chiesto di implementare un quicksort.
Wug

1
@Sam Inoltre, ~~converte in un numero intero, al contrario di +.
Inkbug,

1
@Wug È codegolf, quindi non si tratta di efficienza se non specificato nell'attività.
defhlt

3
+1 per sfruttare diverse basi. È una delle mie tecniche di golf JavaScript preferite.
DocMax,

6

C 83 caratteri

Il numero da dividere viene passato attraverso stdin e lo restituisce come codice di uscita da main() (% ERRORLEVEL% in CMD). Questo codice abusa di alcune versioni di MinGW in quanto quando le ottimizzazioni non sono attive, considera l'ultimo valore di assegnazione come un'istruzione di ritorno. Probabilmente può essere ridotto un po '. Supporta tutti i numeri che possono adattarsi a unint

Se negazione unaria (-) non è consentita: (129)

I(unsigned a){a=a&1?I(a>>1)<<1:a|1;}main(a,b,c){scanf("%i",&b);a=b;a=a<0?a:I(~a);for(c=0;a<~1;a=I(I(I(a))))c=I(c);b=b<0?I(~c):c;}

Se negato unario È permesso: (123)

I(unsigned a){a=a&1?I(a>>1)<<1:a|1;}main(a,b,c){scanf("%i",&b);a=b;a=a<0?a:-a;for(c=0;a<~1;a=I(I(I(a))))c=I(c);b=b<0?-c:c;}

EDIT: ugoren mi ha fatto notare che - ~ è un incremento ...

83 Caratteri se negato unario è permesso: D

main(a,b,c){scanf("%i",&b);a=b;a=a<0?a:-a;for(c=0;a<~1;a=-~-~-~a)c=-~c;b=b<0?-c:c;}

Se il negato unario è permesso, lo x+3è -~-~-~x.
ugoren,

Grazie per questo. Non so perché non mi sia mai venuto in mente. Immagino di non aver capito che potresti impilare gli unari così gratuitamente hehe.
Kaslai,

5

C, 139 caratteri

t;A(a,b){return a?A((a&b)<<1,a^b):b;}main(int n,char**a){n=atoi(a[1]);for(n=A(n,n<0?2:1);n&~3;t=A(n>>2,t),n=A(n>>2,n&3));printf("%d\n",t);}

Esegui con il numero come argomento della riga di comando

  • Gestisce numeri sia negativi che positivi

test:

 ./a.out -6            -2
 ./a.out -5            -1
 ./a.out -4            -1
 ./a.out -3            -1
 ./a.out -2            0
 ./a.out -1            0
 ./a.out 0             0
 ./a.out 1             0
 ./a.out 2             0
 ./a.out 3             1
 ./a.out 4             1
 ./a.out 5             1
 ./a.out 6             2
 ./a.out 42            14
 ./a.out 2011          670

modifiche:

  • salvato 10 caratteri mischiando l'aggiunta (A) per rimuovere le variabili locali.

1
Ben fatto. Ho fatto del mio meglio per bit twiddling e sono arrivato a 239. Non riesco proprio a muovermi la testa A, la mia funzione controlla solo il bit i nel numero n. Lo standard C consente di omettere le dichiarazioni di tipo o è qualcosa del compilatore?
shiona,

1
C assumerà int se non specificato.
Wug

5

ZSH - 31 20/21

echo {2..x..3}|wc -w

Per numeri negativi:

echo {-2..x..3}|wc -w

Con numeri negativi (ZSH + bc) -62 61

Probabilmente non dovrei dare due programmi come risposta, quindi eccone uno che funziona per qualsiasi segno di numero:

echo 'obase=10;ibase=3;'`echo 'obase=3;x'|bc|sed 's/.$//'`|bc

Questo utilizza lo stesso trucco di conversione di base della risposta di Artem Ice .


5

C, 81 73 caratteri

Supporta solo numeri non negativi.

char*x,*i;
main(){
    for(scanf("%d",&x);x>2;x=&x[~2])i=&i[1];
    printf("%d",i);
}

L'idea è di usare l'aritmico puntatore. Il numero viene letto nel puntatore x, che non punta da nessuna parte. &x[~2]= &x[-3]= x-3viene utilizzato per sottrarre 3. Questo viene ripetuto fino a quando il numero è superiore a 2. iconta il numero di volte in cui viene effettuato ( &i[1]= i+1).


Stai cercando di capire il codice, qualcuno ha fatto luce? Grazie
Cong Hui,

@Chui, aggiunta spiegazione.
ugoren,

@ugoren per quanto ne so, printf ("% d") non dovrebbe stampare il puntatore dell'indirizzo di memoria che ho in esadecimale? perché sta stampando un numero intero? o char * sono stato inizializzato per puntare all'indirizzo di memoria 0 per impostazione predefinita? Grazie
Cong Hui,

5

Giava 86 79

Supponiamo che il numero intero sia in y:

Converte in una stringa in base 3, rimuove l'ultimo carattere (spostamento a destra ">>" in base 3), quindi converte nuovamente in numero intero.

Funziona con numeri negativi.

Se il numero, y, è <3 o> -3, allora dà 0.

System.out.print(~2<y&y<3?0:Long.valueOf(Long.toString(y,3).split(".$")[0],3));

Prima pubblicazione su code golf. =) Quindi non posso ancora commentare.

Grazie Kevin Cruijssen per i suggerimenti.


So che è stato più di due anni fa, ma puoi giocare a golf in alcune parti: &&a &e 2x Integera Long. (Inoltre, perché usi ~2invece di solo -3? Hanno lo stesso numero di byte.)
Kevin Cruijssen,

1
@KevinCruijssen Così nostalgico di modificare il mio primo post dopo così tanto tempo. Non ero troppo sicuro del perché pensassi che ~ 2 fosse meglio allora.
Vectorized

2
@KevinCruijssen bene, la sfida dice che non ti è permesso usare -, ma non so se questo contenga per negazione unaria.
FlipTack

@FlipTack Ah hai perfettamente ragione. In tal caso, dimentica che l'ho mai detto. :)
Kevin Cruijssen l'

4

Python2.6 ( 29 ) ( 71 ) ( 57 ) ( 52 ) (43)

z=len(range(2,abs(x),3))
print (z,-z)[x<0]

print len(range(2,input(),3))

Modifica - Ho appena capito che dobbiamo gestire anche numeri negativi. Risolverà più tardi

Modifica2 - Risolto

Modifica3 - Hai salvato 5 caratteri seguendo i consigli di Joel Cornett

Edit4 - Poiché l'input non deve necessariamente provenire da STDIN o ARGV, è stato salvato 9 caratteri non prendendo input da stdin


Vai avanti conabs()
defhlt

più breve da fareprint z if x==abs(x) else -z
Joel Cornett

meglio ancora,print (z,-z)[x<0]
Joel Cornett,

@ArtemIce grazie, ho solo capito che avrei potuto usarlo dopo aver letto un'altra risposta sopra.
elssar,

@JoelCornett humm, non lo sapevo, grazie
elssar il

4

Javascript, 47 29

Utilizza evalper generare dinamicamente a /. Utilizza +solo per la concatenazione di stringhe, non per l'aggiunta.

alert(eval(prompt()+"\57"+3))

EDIT: usato al "\57"posto diString.fromCharCode(47)


-1 per alert(eval(prompt()+"\573"))?
Shieru Asakoto,

4

Rubino ( 43 22 17)

Non solo golf, ma anche eleganza :)

p Rational gets,3

L'output sarà simile (41/1). Se deve essere un numero intero, allora dobbiamo aggiungere .to_ial risultato, e se passiamo to_ia to_fallora potremo ottenere l'output anche per i float.


1
Funziona senza la rationalriga richiesta su Ruby 1.9.3. L'omissione delle parentesi consente di risparmiare un altro carattere .
steenslag,

4

TI-Basic, 8 byte

Vincitore? :)

int(mean({Ans,0,0

PS Arrotonda all'infinito per numeri negativi (vedi qui per il perché). Per arrotondare a zero invece, sostituire int(con iPart(per nessuna modifica di byte.

Casi test

-4:prgmDIVIDE
              -2
11:prgmDIVIDE
               3
109:prgmDIVIDE
              36

3

Python 2.x, 54 53 51

print' -'[x<0],len(range(*(2,-2,x,x,3,-3)[x<0::2]))

Dov'è _il dividendo ed è inserito come tale.

>>> x=-19
>>> print' -'[x<0],len(range(*(2,-2,x,x,3,-3)[x<0::2]))
- 6

Nota: non sono sicuro se è consentito l'uso dell'interprete interattivo, ma secondo l'OP: "L'ingresso può essere su STDIN o ARGV o inserito in altro modo"

Modifica: ora per Python 3 (funziona in 2.x, ma stampa una tupla). Funziona con negativi.


Funziona anche in Python 3?
Lumaca meccanica

Non deve essere abbonabile; avere __len__è abbastanza.
Lumaca meccanica

len(range(100,1000))9003.2.3 su Linux.
Lumaca meccanica

Questo non funziona per i numeri negativi. Ed len(xrange(0,_,3))è comunque più breve e notevolmente più veloce.
grc

@Mechanicalsnail: punto preso. Concedo. Funziona il 3.
Joel Cornett,

3

C ++, 191

Con main e include, il suo 246, senza main e include, è solo 178. Newline conta come 1 carattere. Considera tutti i numeri come non firmati. Non ricevo avvisi per il ritorno principale di un int senza segno, quindi è giusto.

La mia prima presentazione di codegolf in assoluto.

#include<iostream>
#define R return
typedef unsigned int U;U a(U x,U y){R y?a(x^y,(x|y^x^y)<<1):x;}U d(U i){if(i==3)R 1;U t=i&3,r=i>>=2;t=a(t,i&3);while(i>>=2)t=a(t,i&3),r=a(r,i);R r&&t?a(r,d(t)):0;}U main(){U i;std::cin>>i,std::cout<<d(i);R 0;}

usa i turni per dividere il numero per 4 ripetutamente e calcola la somma (che converge in 1/3)

pseudocodice:

// typedefs and #defines for brevity

function a(x, y):
    magically add x and y using recursion and bitwise things
    return x+y.

function d(x):
    if x = 3:
        return 1.
    variable total, remainder
    until x is zero:
        remainder = x mod 4
        x = x / 4
        total = total + x
    if total and remainder both zero:
        return 0.
    else:
        return a(total, d(remainder)).

A parte questo, potrei eliminare il metodo principale nominando d main e facendolo prendere un carattere ** e usando i valori di ritorno dei programmi come output. Restituirà il numero di argomenti della riga di comando diviso per tre, arrotondato per difetto. Questo porta la sua lunghezza al 191 pubblicizzato:

#define R return
typedef unsigned int U;U a(U x,U y){R y?a(x^y,(x|y^x^y)<<1):x;}U main(U i,char**q){if(i==3)R 1;U t=i&3,r=i>>=2;t=a(t,i&3);while(i>>=2)t=a(t,i&3),r=a(r,i);R r&&t?a(r,d(t)):0;}

3

Golfscript - 13 caratteri

~3base);3base

non sembra gestire input negativi
ris.

1
@res s/seem to //:(. Dovrò pensarci
gnibbler

3

PowerShell 57 o 46

In 57 caratteri utilizza %come operatore foreach PowerShell, non modulo. Questa soluzione può accettare numeri interi positivi o negativi.

(-join(1..(Read-Host)|%{1})-replace111,0-replace1).Length

In 46 caratteri se *è consentito come operatore di ripetizione stringa, non moltiplicare. Questa opzione richiede numeri interi positivi come valori di input.

("1"*(Read-Host)-replace111,0-replace1).Length

Se mai torni, ho pubblicato una correzione di bug. Se vuoi che elimini il mio e incorpori la modifica nel tuo, fammelo sapere.
Veskah,

3

R

Funzionano solo con numeri interi positivi:

max(sapply(split(1:x,1:3), length))
# Gives a warning that should be ignored

O:

min(table(rep(1:3, x)[1:x]))

O:

length((1:x)[seq(3,x,3)])

O:

sum(rep(1,x)[seq(3,x,3)])

[[EDIT]] E brutto:

trunc(sum(rep(0.3333333333, x)))

[[EDIT2]] Più probabilmente il migliore - ispirato al codice matlab sopra di Elliot G:

length(seq(1,x,3))

Volevo implementare la stessa idea della tua EDIT2 ma non funziona con numeri negativi:wrong sign in 'by' argument
Andreï Kostyrka,

3

SmileBASIC, 58 51 36 byte (nessuna funzione matematica!)

INPUT N
BGANIM.,4,-3,N
WAIT?BGROT(0)

Spiegazione:

INPUT N           'get input
BGANIM 0,"R",-3,N 'smoothly rotate background layer 0 by N degrees over 3 frames
WAIT              'wait 1 frame
PRINT BGROT(0)    'display angle of layer 0

Il programma sposta uniformemente il livello di sfondo su 3 fotogrammi, quindi ottiene l'angolo dopo 1 fotogramma, quando ha percorso 1/3 della sua distanza totale.

Versione Float Division, 38 byte:

INPUT N
BGANIM.,7,-3,N
WAIT?BGVAR(0,7)

Spiegazione:

INPUT N           'input
BGANIM 0,"V",-3,N 'smoothly change layer 0's internal variable to N over 3 frames
WAIT              'wait 1 frame
PRINT BGVAR(0,7)  'display layer 0's internal variable

3

Haskell 41 39 caratteri

Funziona con l'intero set di numeri interi positivi e negativi

f n=sum[sum$1:[-2|n<0]|i<-[3,6..abs n]]

Innanzitutto crea un elenco di 1 o (-1) (a seconda del segno dell'input) per ogni terzo intero da 0 fino all'input n. abs(n)per i numeri negativi inclusi.

per esempio n=8 -> [0,3,6]

Restituisce quindi la somma di questo elenco.


Non funziona su numeri negativi (-3/3 è -1 non 1).
Cormac,

Bello, l'hai fatto funzionare su numeri negativi ma non puoi usare /, leggi le specifiche.
Cormac,

Oddio, mi hai preso due volte. Tutto risolto;)
Charl Kruger il

Bello! Btw Puoi ottenere 39 caratteri con fn = sum [somma $ 1: [- 2 | n <0] | i <- [3,6..abs n]]
Cormac

2

Clojure, 87; lavora con negativi; basato su lazyseqs

(defn d[n](def r(nth(apply interleave(repeat 3(range)))(Math/abs n)))(if(> n 0)r(- r)))

Ungolfed:

(defn d [n]
  (let [r (nth (->> (range) (repeat 3) (apply interleave))
               (Math/abs n))]
        (if (pos? n)
          r
          (- r))))

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.