Confronta i numeri di versione


26

Quando pubblichiamo del software, gli assegniamo un numero di versione. E gli utenti potrebbero voler aggiornare all'ultima versione di alcuni software. Quindi, è il momento di scoprire quale versione dovrebbe essere più recente.

Ingresso

Immettere due numeri di versione come stringhe.

Nel contesto di questa sfida, supportiamo solo numeri di versione che sono alcune cifre unite da punti.

  • Un numero di versione è una stringa che può contenere solo cifre ( 0~ 9) e punti ( .).
  • I punti non sarebbero il primo / ultimo carattere di un numero di versione.
  • Ci devono essere alcune cifre tra i punti. Non è possibile che vengano visualizzati continuamente due punti.
  • Tutti i numeri in un numero di versione sarebbero inferiori a 2 16 .

Produzione

Confronta i numeri di versione immessi e visualizza se il primo è maggiore di / uguale a / minore del secondo. Puoi scegliere una delle seguenti presentazioni:

  • Usa numero positivo / zero / numero negativo, mentre zero significa uguale;
  • Usa tre valori distinti costanti;

confrontando

Non è necessario implementare l'algoritmo descritto in questa sezione. Il tuo invio è valido fintanto che risulta lo stesso output con questo algoritmo.

  • I numeri di versione sono alcuni numeri decimali uniti da punti. Dapprima abbiamo diviso i due numeri di versione in matrici di numeri;
  • Riempiendo la fine degli array con zeri per farli avere la stessa lunghezza;
  • Confronta dal primo elemento all'ultimo:
    • Se i due elementi dell'array sono diversi, il numero maggiore indica un numero di versione maggiore
    • Se sono uguali, continua a confrontare i seguenti elementi;
    • Se tutti gli elementi dell'array sono uguali, le due versioni sono uguali.

Casi test

version1  version2  result
2         1         >
1.0.0     1         =
1.0       1.0.0     =
1.2.42    1.2.41    >
1.1.56789 1.2.0     <
1.10      1.2       >
1.20      1.150     <
18.04     18.4      =
7.010     7.8       >
1.0.0.1.0 1.00.00.2 <
00.00.01  0.0.0.1   >
0.0.1     0.1       <
42.0      4.2.0     >
999.999   999.999.1 <
2018.08.1 2018.08   >


.NET ha un oggetto Version, ma non è supportato un singolo carattere :(
Brian J

@BrianJ e aggiungere '0' a molti personaggi? :)
RobAu,

Bene, si aspetta in realtà 2, 3 o 4 porzioni. Quindi fallisce nel caso di test 1.0.0.1.0 (anche se inizialmente ho provato la tua idea :))
Brian J,

Penso che Windows abbia un built-in che farà questo: StrCmpLogicalW
bace1000

Risposte:



6

05AB1E (legacy) , 15 14 13 byte

'.¡0ζε`.S}0K¬

Uscite -1 [] 1per < = >rispettivamente.

-1 byte grazie a @Emigna .

Provalo online o verifica tutti i casi di test .

Spiegazione:

'.¡              # Split on dots
                 #  i.e. ['1.0.1.1.0','1.00.2.0']
                 #   → [['1','0','1','1','0'],['1','00','2','0']]
   0ζ            # Zip, swapping rows and columns, using '0' as filler
                 #  i.e. [['1','0','1','1','0'],['1','00','2','0']]
                 #   → [['1','1'],['0','00'],['1','2'],['1','0'],['0','0']]
     ε   }       # Map each:
      `          #  Push both values to the stack
       .S        #  And calculate the signum (1 if a>b; -1 if a<b; 0 if a==b)
                 #   i.e. [['1','1'],['0','00'],['1','2'],['1','0'],['0','0']]
                 #    → [0,0,-1,1,0]
          0K     # Remove all zeros
                 #  i.e. [0,0,-1,1,0] → [-1,1]
            ¬    # Then take the head as result
                 #  i.e. [-1,1] → -1

1
Puoi usare 0Kinvece di ʒĀ}.
Emigna,

@Emigna Ah ovviamente .. Grazie.
Kevin Cruijssen,

5

R , 32 byte

rank(numeric_version(scan(,"")))

Provalo online!

Usando un R incorporato

Uscite 1 2, 1.5 1.5, 2 1per meno, uguale, maggiore.


Meglio finora, senza incorporato:

R , 151 142 125 125 107 byte

function(v,L=strsplit(v,'\\.'))Find(c,sign(Reduce('-',Map(as.double,Map(c,L,Map(rep,0,rev(lengths(L))))))))

Provalo online!

Codice srotolato con spiegazione:

function(v){             # character vector of 2 elements as function arg;
  L=strsplit(v,'\\.')    # obtain a list of two character vectors
                         # with the separated version numbers;
  R=rev(lengths(L))      # store in vector R the lengths of the 2 vectors and reverse it;
  M1=Map(rep,0,R)        # create a list of 2 vector containing zeros
                         # repeated R[1] and R[2] times;
  M2=Map(c,L,M1)         # append to the vectors in list L the zeros in M1;
  M3=Map(as.double,M2)   # convert the character vectors in M2 to double;
  w=sign(Reduce('-',M3)  # compute the sign of element by element difference M[[1]] - M[[2]]);
  Find(c,w)            # returns the first non zero element in w, if none return NULL;
}
# N.B. as.double is necessary because "0XX" is interpreted as octal by strtoi unless 
#      we use strtoi(x,10) which is exactly the same length of as.double(x)

Uscite -1, NULL, 1per meno, uguale, maggiore.


Concetto originale, golfed verso il basso utilizzando sapply, [<-e %*%:

R , 129 byte

function(x,y=strsplit(x,"\\."),w=sign(sapply(y,function(x)strtoi("[<-"(rep(0,max(lengths(y))),seq(x),x),10))%*%c(1,-1)))w[!!w][1]

Provalo online!

Ora hai un elenco di due vettori di numeri interi di uguale lunghezza. Calcola le differenze a coppie usando Reduceed emetti il ​​primo elemento diverso da zero usando la piccola w[!!w][1]forma complicata alla fine.

Uscite -1, NA, 1per meno, uguale, maggiore.


Impressionante! Quick golf: newline extra alla fine del codice - dovrebbe essere di 150 byte;)
JayCe

ridurre il numero di variabili denominate ... . Sento che c'è un modo per farlo usando una matrice anziché le liste ma non ho ancora trovato il modo di farlo.
JayCe,

1
È possibile ottenere questo fino a 100 byte utilizzando scan function(a,b,d=scan(t=a,se='.'),e=scan(t=b,se='.'),f=1:max(lengths(list(d,e))),g=d[f]-e[f])g[!!g][1](o 106 se si desidera restituire -1, NA, 1 non (negativo), NA, (positivo).
tunnel

1
@mnel la soluzione da 100 byte richiede un po 'di lavoro. Fallisce negli ultimi due casi di test. L'imbottitura deve essere 0e non (implicitamente) NA. Ho reso la risposta un Wiki della comunità in modo che chiunque possa aggiustarlo possa semplicemente aggiungerlo.
ngm

1
@digEmAll ha giocato a golf 4 byte calcolando prima il segno, quindi fare Find(c,x). Penso che sia un nuovo trucco.
JayCe,

4

APL (Dyalog Unicode) , 18 17 byte

1 byte salvato grazie a @ Adám per l'utilizzo ⍤1anziché ∘↑(...)¨e la modifica del formato di input da una matrice nidificata a una matrice

(⍋-⍒)(⍎¨∊∘⎕D⊆⊢)⍤1

Provalo online!

Prende l'input come una matrice di caratteri come argomento corretto, in cui ogni stringa di versione si trova sulla propria riga. Uscite ¯1 1, 0 0, 1 ¯1per <, =, >rispettivamente.

(⍎¨∊∘⎕D⊆⊢)⍤1 su ogni riga

  • ∊∘⎕D⊆⊢ raggruppare tutte le occorrenze di cifre, ovvero dividere .

  • ⍎¨ e converti ciascuna di queste occorrenze in un numero

converti in una matrice, dove il primo input è nella riga superiore e il secondo nella parte inferiore, riempiendo con 0s dove necessario

(⍋-⍒) e

  • - sottrarre
    • gli indici nelle righe che li ordinerebbero in ordine decrescente
    • uguale al top ma per ordine crescente

4

Perl 6 , 63 47 22 byte

{"v$^a cmp v$^b".EVAL}

Provalo online!

Si scopre che Perl 6 ha un tipo di versione che si adatta praticamente alla descrizione. Si tratta di un blocco di codice anonimo che prende una lista di due stringhe di versione e restituisce uno More, Sameo Less.

Spiegazione:

{                    }  # Anonymous code block
 "             "        # Create a string of code
  v$^a cmp v$^b         # Comparing the two versions
                .EVAL   # And EVAL it

Oppure, senza tipi predefiniti per 47 byte:

{first +*,[Z<=>] map *.split('.')[^@_.ords],@_}

Provalo online!

Blocco di codice anonimo che accetta due stringhe e restituisce Morese la seconda è maggiore, Lessse la seconda è più piccola e Nilse sono uguali.

Spiegazione:

{                                             } # Anonymous code block
                 map *.split('.')          ,@_  # Split both strings by '.'
                                 [^@_.ords]     # Pad the lists by a lot
          [Z<=>]   # Zip the strings with the <=> operator
 first +*,  # Get the first value that when coerced to an int, is not 0

3

Brachylog , 49 40 byte

+0|{~c[H,".",T]hị;T|ị;0|0}ᵐz{h-0&t↰₀|h-}

... È ancora piuttosto poco lungo.

Si aspetta un elenco di due stringhe. Usa positive number / zero / negative number come > / = / <.

Provalo online!

Spiegazione

Dividere gli input

Dato un input che non si unisce [0, 0], come ad esempio ["1.02.0", "1.2.0.1.0"]le uscite del segmento sottostante, ad es [[1, "02.0"], [1, "2.0.1.0"]].

                            # unify the input with...
+0                          # : a list whose sum = 0 (output is 0)
  |{                     }ᵐ # : OR a list that when mapped...
    ~c                      # : : if the input string unifies with a list of the form...
      [H,".",T]             # : : : e.g. "1.02.0", H = "1", T = "02.0"
               hị           # : : : coerce the head to an integer
                 ;T         # : : : append the string T
                            # : : : "1.02.0" -> [1, "02.0"]
                   |ị       # : : OR it unifies with an integer
                     ;0     # : : : append 0
                            # : : : "1" -> [1, 0]
                       |0   # : : OR it unifies with 0
                            # : : : 0 -> [0]

Confronto degli input

Dato, ad esempio, [[1, "02.0"], [1, "2.0.1.0"]]comprime le liste secondarie [[1, 1], ["02.0", "2.0.1.0"]]e confronta i valori in head ( [1,1]). Ricorrere al secondo elenco secondario. Si noti che il predicato zip zscorre ciclicamente gli elenchi più brevi in ​​modo che zippare con [0,0]sia equivalente a zippare con [0], quindi il passaggio precedente si unisce 0con 0senza ulteriori valori aggiunti.

z             # zip the sublists
 {          } # unify the result (r) with...
  h           # : take the head of the result
   -          # : : subtract the second value from the first
    0         # : : if the difference unifies with 0...
     &t↰₀     # : : recur on the tail of r
         |h-  # : OR unify with the difference of the elements of the head
              # : (equivalent to returning early)

3

JavaScript (ES6), 73 68 byte

5 byte salvati grazie a @redundancy

(a)(b)0

a=>b=>(a+[...b].fill`.`).split`.`.some((x,i)=>d=~b.split`.`[i]-~x)*d

Provalo online!


Bello. Se ho capito bene, puoi salvare i byte sostituendoli replacecon fill. Gli operandi per -vengono scambiati poiché entrambi devono ora essere forzati in un numero. Provalo online!
ridondanza il

@redundancy Buona idea! (Non sono sicuro che la mia implementazione sia esattamente ciò che avevi in ​​mente, però.)
Arnauld,

Ho ipotizzato che il tuo intento fosse quello di aggiungere abbastanza valori coercibili a 0 in modo tale che la mappatura sulle sottostringhe aalla fine cicla attraverso quei valori 0 se bcontiene più segmenti numerici di a. Succede così che il metodo più breve per assicurarsi che sia così è quello di dividere su una bstringa di lunghezza "." sfruttando la divisione esistente applicata a a.
ridondanza il

3

Java (JDK 10) , 201 96 89 byte

java.util.Comparator.comparing(java.lang.module.ModuleDescriptor.Version::parse)::compare

Provalo online!

Restituisce un numero negativo se la prima versione è più piccola della seconda, positiva se la prima versione è maggiore della seconda e 0se sono uguali.

Sì, è un lavoro pesante per "solo" chiamare un built-in!

Crediti


1
Ho provato, ma sono in grado di rimuovere solo tre byte .. 228 byte
Kevin Cruijssen,

1
Trovato qualcosa in più: 217 byte
Kevin Cruijssen,

1
Probabilmente è tutto .. Già provato, try-finallyquindi if-check può essere semplificato; provato a tornare all'interno del ciclo se t!=0; provato ad usare Integere i.compare(i.valueOf(...),i.valueOf(...)); provato a usare generici come questo <T>T[]g(T s){return(T[])(s+"").replaceAll("(\\.0+)*$","").split("\\.");}; ecc. Tutti sono più lunghi di 2-6 byte. Se tu (o chiunque altro) trovi qualcosa in più, fammi sapere per favore. Curioso di sapere cosa. :)
Kevin Cruijssen il

1
@KevinCruijssen No, non posso perché "Tutti i numeri in un numero di versione sarebbero inferiori a 2^16". Brevi intervalli da - (2 ^ 15) a 2 ^ 15-1.
Olivier Grégoire,

1
@KevinCruijssen Potrei rimuovere 105 byte! Come? Bene, ho trovato un built-in;)
Olivier Grégoire


2

Retina 0.8.2 , 54 byte

\d+
$*
+`^(.)(.*=)\1
$2
(.*=|^=.*)1.*
<
.*1.*=.*
>
\.

Provalo online! Il link include casi di test. Utilizza il valore del separatore come output di uguaglianza, quindi per comodità l'intestazione converte il separatore di input in =ma potrebbe essere qualsiasi cosa non presente [.\d]. Spiegazione:

\d+
$*

Converti in unario.

+`^(.)(.*=)\1
$2

Elimina ripetutamente il primo carattere da ogni lato fino a quando differiscono o si esaurisce un lato. Questo è molto più veloce del tentativo di abbinare i prefissi, anche se forse non è più golfista. A questo punto, le stringhe sono in una delle diverse forme, che devono essere decodificate in un risultato di confronto.

  1. Se nessuna delle stringhe contiene a, 1il risultato è=
  2. Se la stringa sinistra inizia con a, 1il risultato è>
  3. Se la stringa giusta inizia con a, 1il risultato è<
  4. Se la stringa sinistra è vuota, il risultato è <
  5. A questo punto la stringa giusta è vuota, quindi il risultato è >

Un altro modo di pensare a questo è che se una stringa contiene a 1e l'altra non inizia con a 1allora quella stringa è maggiore, tuttavia risulta essere un byte più lungo.

(.*=|^=.*)1.*
<

Controllare caso 3 o caso 4 senza caso 1.

.*1.*=.*
>

Se la stringa sinistra contiene ancora a 1a questo punto, allora è maggiore.

\.

In caso contrario, eliminare eventuali .residui.

Console Browser Firefox REPL, 19 byte

Services.vc.compare

Credo che questa funzione interna esegua il confronto richiesto. Restituisce -1, 0 o 1.


1
Ti suggerirei di pubblicare il codice Chrome di Firefox come un'altra risposta ...
tsh

a proposito, non sono sicuro di come il codice Chrome di Firefox conti i suoi byte. Dovrebbe Cu.import("resource://gre/modules/Services.jsm");essere contato?
TSH

1
@tsh Ecco perché ho aggiunto "Browser Console REPL" ...
Neil

2

PHP , 38 byte

<?=version_compare($argv[1],$argv[2]);

Uscite -1 → < | 0 → = | 1 → >

Provalo online!


Penso che la tua presentazione possa essere solo la funzione stessa
Jo King,

1
Ciò restituisce il risultato errato per qualsiasi coppia di input che differisce solo per gli zero finali, ad esempio 1.0.0e1
oktupol

2

C (gcc) ,  140  134 byte

Questo codice produce un negativo, 0o un positivo per <, =o >rispettivamente.

i;n;p;q;g(char*s){for(i=n=0;*s&&++n&&*s-46;i=i*10+*s++-48);i=i;}f(char*a,char*b){for(p=q=0;*a+*b&&p==q;b+=n)p=g(a),a+=n,q=g(b);a=p-q;}

Provalo online!

modifiche:

  • 6 byte salvati grazie a ceilingcat!

La sfida afferma: "Usa tre valori distinti costanti;" Il tuo codice non restituisce costanti.
Olivier Grégoire,

1
@Olivier Dichiara che posso "Utilizzare tre valori distinti costanti;" OPPURE "Usa numero positivo / zero / numero negativo, mentre zero significa uguale;"
Annyo,

Colpa mia! Hai ragione.
Olivier Grégoire,


1

JavaScript (Node.js) , 105 88 80 byte

-17 byte da @redundancy. Wow!

-8 byte rimuovendo Math.sign. Grazie @tsh

Restituisce un valore negativo, zero o positivo

f=(a,b,r=/(\d*).?(.*)/)=>a+b&&+((a=r.exec(a))[1]-(b=r.exec(b))[1]||f(a[2],b[2]))

Provalo online!


1
88 byte usando execper dividere le stringhe. Provalo online!
ridondanza il

@ ridondanza Accidenti, grazie! è un bel trucco
Luis felipe De jesus Munoz,

Forse vuoi rimuovere Math.sign per salvare alcuni byte passando a valori positivi / zero / negativi. E forse è necessario un segno positivo.
TSH


0

Pulito , 116 111 byte

import StdEnv,Text
?s=map toInt(split"."s)
$a b= @(?a)(?b)
@[h:t][u:v]|h==u= @t v=h-u
@l[]=sum l
@[]l= ~(sum l)

Provalo online!

Emette un numero negativo quando il primo argomento è inferiore al secondo, zero quando sono equivalenti e un numero positivo quando è maggiore del secondo.


0

Swift 4 , 155 byte

Header (non conteggiato: il codice non è ricorsivo):

let f:(String,String)->Bool? = 

Codice

{let x:(String)->[Int]={$0.split{$0=="."}.map{Int($0)!}.reversed().drop{$0==0}.reversed()},a=x($0),b=x($1)
return a==b ?nil:a.lexicographicallyPrecedes(b)}

Provalo online!

spiegazioni

  • Tagliamo il finale 0.
  • Confrontiamo i componenti numericamente.

Costanti restituite

  • zero per =
  • vero per <
  • falso per>

0

JavaScript 64 byte

a=>b=>(e=i=>(g=v=>v.split`.`[i]||0)(a)-g(b)||!a[i]-1&&e(i+1))(0)

Provalo online!

Con commenti:

a=>b=>(                            // Main function takes arguments like ("1.2.42")("1.2.41")
    e=i=>                          // e(i) compares the ith number, returns >0, <0 or =0.
        (   g=v=>v.split`.`[i]||0  // g() returns the ith string or 0
        )(a)                       // call g(a)
        -g(b)                      // subtracting g(b) from g(a) casts strings to integer
        ||                         // If they are not equal return result now
        !a[i]-1 &&                 // recursion limited to a.length, always sufficient
        e(i+1)                     // next i
    )(0)                           // Start with i = 0


0

Burlesque - 17 byte

wd{'.;;)ri}m[^pcm


blsq ) "2018.08.1 2018.08"wd{'.;;)ri}m[^pcm
1
blsq ) "0.0.1 0.1"wd{'.;;)ri}m[^pcm
-1
blsq ) "1.1.56789 1.2.0"wd{'.;;)ri}m[^pcm
-1

Se vuoi l'output in '> <=', aggiungi ?i"<=>"j!!Q.


0

Powershell, 88 byte

Restituisce 0uguale, positive integera maggiore o negative integerminore di.

param($a,$b)+(($x=$a-split'\.')+($y=$b-split'\.')|%{$x[+$i]-$y[$i++]}|?{$_}|Select -f 1)

Script di test meno golfato:

$f = {

param($a,$b)
$x=$a-split'\.'
$y=$b-split'\.'
$z=$x+$y|%{
    $x[+$i]-$y[$i++]
}|?{$_}|Select -first 1
+$z             # convert $null to 0

}

@(
    ,("2"         ,"1"         , 1)
    ,("1.0.0"     ,"1"         , 0)
    ,("1.0"       ,"1.0.0"     , 0)
    ,("1.2.42"    ,"1.2.41"    , 1)
    ,("1.1.56789" ,"1.2.0"     ,-1)
    ,("1.10"      ,"1.2"       , 1)
    ,("1.20"      ,"1.150"     ,-1)
    ,("18.04"     ,"18.4"      , 0)
    ,("7.010"     ,"7.8"       , 1)
    ,("1.0.0.1.0" ,"1.00.00.2" ,-1)
    ,("00.00.01"  ,"0.0.0.1"   , 1)
    ,("0.0.1"     ,"0.1"       ,-1)
    ,("42.0"      ,"4.2.0"     , 1)
    ,("999.999"   ,"999.999.1" ,-1)
    ,("2018.08.1" ,"2018.08"   , 1)
) | % {
    $v1,$v2,$expected = $_
    $result = &$f $v1 $v2
    "$([Math]::Sign($result)-eq$expected): $result"
}

Produzione:

True: 1
True: 0
True: 0
True: 1
True: -1
True: 8
True: -130
True: 0
True: 2
True: -1
True: 1
True: -1
True: 38
True: -1
True: 1

0

Dardo , 277 231 byte

F(s,{t}){t=s.split('.').map(int.parse).toList();while(t.last<1)t.removeLast();return t;}f(a,b,{d,e,f,g,h,i=0}){d=F(b);e=F(a);g=d.length;h=e.length;f=h>g?g:h;for(;i<f;i++)if(e[i]!=d[i])return e[i]>d[i]?1:-1;return h>g?1:(h<g?-1:0);}

Provalo online!

  • -44 byte usando le variabili per memorizzare la lunghezza e usando ternary in loop
  • -2 byte rimuovendo le parentesi for

0

Swift 4 + Foundation , 160 byte (142 + 18) , 155 byte (142 + 13)

Importazione (13 byte, inclusi ; per separare dal codice):

Questo importerà Foundation, ma è 5 byte più corto di import Foundation.

import UIKit;

Header (non conteggiato: il codice non è ricorsivo):

let f:(String,String)->ComparisonResult =

Codice (142 byte):

{var x={($0 as String).split{$0=="."}.count},a=$0,b=$1
while x(a)<x(b){a+=".0"}
while x(b)<x(a){b+=".0"}
return a.compare(b,options:.numeric)}

Provalo online!

spiegazioni

  1. Aggiungiamo alcuni 0 finali finali per lo stesso numero di componenti.
  2. Confrontiamo i componenti numericamente.

Costanti restituite

  • ComparisonResult.orderedSame per =
  • ComparisonResult.orderedAscending per <
  • ComparisonResult.orderedDescending per>

Non sono sicuro se contiamo l' importistruzione, quindi ho pubblicato una risposta separata che non richiede Foundatione con un conteggio tra 142 byte (senza contare l'importazione) e 160 byte (conteggio dell'importazione).
Cœur il

0

Zsh , 54 byte

eval {autoload,}' is-at-least $'{1\ $2,2\ $1}';<<<$?;'

Provalo online! Prova una suite di test!

Questo evalè per le seguenti otto affermazioni:

autoload is-at-least $1 $2     # loads the "is-at-least" function
<<<$?                          # success, prints 0
autoload is-at-least $2 $1     # redundant
<<<$?                          # success, prints 0
is-at-least $1 $2              # exits 1 if $1 < $2
<<<$?
is-at-least $2 $1              # exits 1 if $2 < $1
<<<$?

Quindi i tre valori univoci sono:

 cmp |  value
-----+------------------------------------------
  =  |  0<newline>0<newline>0<newline>0<newline>
  <  |  0<newline>0<newline>1<newline>0<newline>
  >  |  0<newline>0<newline>0<newline>1<newline>
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.