Ordenar una cadena, una especie de


29

Si ordena una cadena, generalmente obtendrá algo como:

         ':Iaaceeefggghiiiiklllllmnnooooprrssstttttuuyyyy

Sí, esa fue la primera oración ordenada.

Como se puede ver, hay una gran cantidad de caracteres repetidos, aa, eee, ttttt, 9 espacios y así sucesivamente.

Si agregamos 128al valor ASCII del primer duplicado, 256al segundo, 384al tercero y así sucesivamente, ordénelo nuevamente y genere la nueva cadena (módulo 128 para recuperar los mismos caracteres) obtenemos la cadena:

 ':Iacefghiklmnoprstuy aegilnorstuy egilosty iloty lt    

(Tenga en cuenta el espacio inicial único y los 4 espacios finales).

La cadena se "ordenadas secuencialmente" <space>':I....uy, <space>aeg....uy, <space>egi....ty, <space>iloty, <space>lt, <space>, <space>, <space>, <space>.

Puede ser más fácil visualizar esto si usamos una cadena con dígitos. La cadena 111222334será cuando "ordenados" ser: 123412312.

Reto:

Para sorpresa, el desafío es escribir un código que clasifique una cadena de acuerdo con la descripción anterior.

Puede suponer que la cadena de entrada contendrá solo caracteres ASCII imprimibles en el rango 32-126 (espacio para tilde).


Casos de prueba:

**Test cases:**
 *:Tacest*es*s*

If you sort a string you'll typically get something like:
 ':Iacefghiklmnoprstuy aegilnorstuy egilosty iloty lt    

Hello, World!
 !,HWdelorlol

#MATLAB, 114 bytes
 #,14ABLMTbesty 1A

f=@(s)[mod(sort(cell2mat(cellfun(@(c)c+128*(0:nnz(c)-1),mat2cell(sort(s),1,histc(s,unique(s))),'un',0))),128),''];
'()*+,-0128:;=@[]acdefhilmnoqrstuz'(),0128@acefilmnorstu'(),12celmnostu'(),12celnstu(),clnst(),cls(),cs(),()()()()

Este es el , por lo que el código más corto en cada idioma contado en bytes ganará ref .


El título es un poco confuso, lo que hace que piense esto e ignore la descripción: tio.run/nexus/05ab1e#@1@td2jh4ZVe//… Un buen desafío de lo contrario, trabajaré en expandir eso para cumplir con el resumen.
Urna de pulpo mágico

¿Podemos generar una lista de caracteres en lugar de una cadena?
Wheat Wizard

Si puede ingresar una cadena, la salida también debe ser una cadena. Si una lista de caracteres es la forma normal de ingresar y emitir cadenas en sus idiomas, entonces está bien. Se puede, por ejemplo, no se emiten {'S', 'g', 'i', 'n', 'r', 't'}en Python, ya que la forma "normal" de hacerlo es "String".
Stewie Griffin

Corregiré mi comentario anterior: una cadena es una lista de caracteres , por lo que se acepta una lista de caracteres de salida. Sin embargo, no se acepta una lista de cadenas . Esto significa que si es posible agregar un segundo carácter a un elemento en su lista, entonces no se acepta. A modo de ejemplo: {'a','b'}no se acepta en Matlab ya que se puede añadir un carácter a cada uno de los personajes como este: {'aa','b'}. Su entrada y salida deben estar en el mismo formato.
Stewie Griffin

@StewieGriffin Cuando dices ordenado según la descripción anterior. ¿Quiere decir que mi algoritmo de clasificación debe seguir el proceso de modificación de los valores ASCII o simplemente tiene que producir la misma salida que ese algoritmo?
George Reith

Respuestas:


15

Pyth, 5 bytes

s.T.g

Banco de pruebas

Muy sencillo: Agrupar y ordenar, transponer, concatenar.

s.T.g
s.T.gkQ    Implicit variables
   .gkQ    Group the input input lists of elements whose values match when the
           identity function is applied, sorted by the output value.
 .T        Transpose, skipping empty values. This puts all first characters into
           a list, then all second, etc.
s          Concatenate.

Pyth tiene todo para convertirse en nuevo J, es increíble
shabunc

3
@shabunc Si quieres ver la nueva J, visita github.com/DennisMitchell/jelly
isaacg el

13

Jalea , 3 bytes

ĠZị

Pruébalo en línea!

Cómo funciona

Oh muchacho, este desafío fue hecho para Jelly.

El grupo atom ( Ġ) toma una matriz 1 como entrada y agrupa índices que corresponden a elementos idénticos de la matriz. La matriz de grupos de índice se ordena con los elementos correspondientes como claves, que es precisamente el orden que necesitamos para este desafío.

A continuación, el átomo zip ( Z) transpone filas y columnas de la matriz de índices generada (irregular). Esto simplemente consiste en leer las columnas de la matriz, omitiendo los elementos que no están presentes en esa columna. Como resultado, obtenemos el primer índice del personaje con el punto de código más bajo, seguido del primer índice del personaje con el segundo punto de código más bajo, ... seguido por el segundo índice del personaje con el punto de código más bajo, etc.

Finalmente, el átomo unindex ( ) recupera los elementos de la matriz de entrada en todos sus índices en el orden generado. El resultado es una matriz de caracteres 2D, que Jelly aplana antes de imprimirla.


1 Jelly no tiene un tipo de cadena , solo conjuntos de caracteres.


"Oh, muchacho, este desafío fue hecho para Jelly". -> respuesta de 3 bytes
geisterfurz007 Detener este caos

Como dije, casi hecho para Jelly. :)
Dennis

10

Python 3, 109 105 104 103 99 93 90 88 81 79 69 bytes

2 bytes guardados gracias a FlipTack

7 bytes guardados porque flornquake captó mi error tonto

2 bytes guardados gracias a xnor

10 bytes guardados gracias a Dennis

a=[*input()]
while a:
    for c in sorted({*a}):print(end=c);a.remove(c)

Explicación

Comenzamos convirtiendo nuestra cadena en una lista usando un splat y almacenando esa lista en una variable a. Luego, aunque nuestra ano es la lista vacía, revisamos cada miembro único dea en orden ordenado, lo imprimimos y eliminamos una copia de ese personaje de la lista.

Cada iteración imprime, por lo tanto, imprime una copia de cada personaje presente en a.


1
@StewieGriffin setes un conjunto sin clasificar.
FlipTack

2
@StewieGriffin cuando se imprimen están ordenados pero no por sus valores ASCII exactamente. A menudo parece que sí, pero creo que están ordenados por algún tipo de hash.
Wheat Wizard

1
Puede hacer funa cadena en lugar de una lista para guardar algunos bytes.
flornquake

1
Si toma a=list(input()), puede hacerlo a.remove(c), lo cual es un ahorro neto.
xnor

1
Cambiar a Python 3 ahorraría muchos bytes. tio.run/nexus/…
Dennis

6

Haskell, 44 bytes

import Data.List
concat.transpose.group.sort

Ejemplo de uso:

Prelude Data.List> concat.transpose.group.sort $ "If you sort a string you'll typically get something like:"
" ':Iacefghiklmnoprstuy aegilnorstuy egilosty iloty lt    "

Ordenar, agrupar caracteres iguales a una lista de cadenas (por ejemplo, "aabbc"-> ["aa","bb","c"]), transponer y aplanar en una sola cadena, nuevamente.


6

Python 2 , 75 bytes

lambda s:`zip(*sorted((s[:i].count(c),c)for i,c in enumerate(s)))[1]`[2::5]

Pruébalo en línea!


1
No sé si es válido pero lambda s:`[sorted((1e9+s[:i].count(c),c)for i,c in enumerate(s))]`[18::21]funciona para cadenas con longitud máxima 9e9.
xnor

@xnor puede soltar []y cambiar 18a 17para guardar dos bytes. lambda s:`sorted((1e9+s[:i].count(c),c)for i,c in enumerate(s))`[17::21]
Wheat Wizard

@xnor Como mínimo, este debería ser un Python golf válido de 32 bits. Traté de deshacerme de él zip, pero no creo 1e9que se me haya ocurrido agregar ... ¡Gracias!
Dennis

@WheatWizard Buen ojo. ¡Gracias!
Dennis

Esto falla si la cadena tiene barras invertidas.
Lynn el

4

Dyalog APL , 21 caracteres = 39 bytes

t[0~⍨∊⍉(⊢⌸t)[⍋∪t←⍞;]]

t[... ] índice t (se definirá en breve) con ...

0~⍨ ceros eliminados de

 el alistado (aplanado)

 transpuesto

(⊢⌸t)[... ;] tecleado * t , indexado por fila por ...

   los índices que ordenarían

   las letras únicas de

  t←t , que tiene el valor de

   entrada de texto solicitada

TryAPL en línea!


⊢⌸tcrea una tabla donde las filas (rellenadas con ceros para una tabla rectangular) enumeran los índices de cada letra única en t .


1
¿Cuál de los glifos es más caro?
ren

1
@wptreanor hace que todo sea UTF-8 en lugar de un byte por char.
Adám

4

C, 109 106 105 104 102 100 97 98 96 91 Bytes

Copia de seguridad de hasta 98 ​​bytes, necesaria para inicializar j para que f (n) sea reutilizable

Hasta 96 Bytes usando pone en lugar de B-)

Es extraño que tuve que retroceder para strlen, pero me libré del ciclo for (; i ++;), así que ahora se ha reducido a 91 Bytes. Al parecer, la página de manual para pone lee;

"RETURNS
   If successful, the result is a nonnegative integer; otherwise, the result is `EOF'."

... tuve suerte de que funcionara en primer lugar

char*c,i,j;f(m){for(j=strlen(m);j;++i)for(c=m;*c;c++)if(*c==i){*c=7,putchar(i),j--;break;}}

código de prueba ...

main(c,v)char**v;
{
    char test[] = "If you sort a string you'll typically get something like: ";
    char test2[] = "Hello, World!";

    f(test);puts("");    
    f(test2);puts("");    
}

Aquí hay algunos casos de prueba, ahora es el momento de jugar golf.

C:\eng\golf>a.exe
 ':Iacefghiklmnoprstuy aegilnorstuy egilosty iloty lt
 !,HWdelorlo

¿Se dejan los espacios finales en el primer caso de prueba?
Stewie Griffin

Tengo tres espacios finales en el primer caso de prueba ... Eso es porque no
incluí

4

Mathematica, 68 60 59 bytes

Split[Characters@#~SortBy~ToCharacterCode]~Flatten~{2}<>""&

Acepta una cadena. Emite una cadena.

Si se permitiera la lista de caracteres (46 bytes):

Split[#~SortBy~ToCharacterCode]~Flatten~{2,1}&

Versión usando Sort(40 bytes):

Split@Sort@Characters@#~Flatten~{2}<>""&

Esta versión no puede ser mi respuesta porque Sortno se puede usar aquí; Sortse ordena por orden canónico, no por código de caracteres.


No sé Mathica, así que esto podría estar bien, pero ¿leíste este comentario?
Stewie Griffin

@StewieGriffin Welp, no. Puedo arreglar eso, pero ¿eso no da una ventaja injusta a los idiomas que no tienen una distinción String vs Char []? Meta discusión relacionada
JungHwan Min

Buen punto. Hice una corrección, vea el comentario debajo del original. ¿Justa? No estoy seguro de si esto hace que su respuesta sea válida o no.
Stewie Griffin

@StewieGriffin Mathematica no tiene una distinción entre caracteres y cadenas. Incluso el Characterscomando genera técnicamente una lista de cadenas de longitud 1.
JungHwan Min

1
@StewieGriffin Creo que esto también es relevante . Creo que es mejor permitir la entrada en cualquier formato razonable, ya sea una cadena, lista de longitud 1 cuerdas, matriz de caracteres, matriz de bytes, etc.
ngenisis


3

JavaScript (ES6), 79 bytes

f=s=>s&&(a=[...new Set(s)]).sort().join``+f(a.reduce((s,e)=>s.replace(e,``),s))
<input oninput=o.textContent=f(this.value)><pre id=o>

Funciona extrayendo el conjunto de caracteres únicos, ordenándolos, eliminándolos de la cadena original y calculando recursivamente el tipo del resto de la cadena. Solución de 81 bytes que me pareció interesante:

f=s=>s&&(s=[...s].sort().join``).replace(r=/(.)(\1*)/g,"$1")+f(s.replace(r,"$2"))

3

J , 16 15 bytes

/:+/@(={:)\;"0]

Este es un verbo que toma y devuelve una cadena. Pruébalo en línea!

Miles ahorró un byte, ¡gracias!

Explicación

Aquí no hay nada demasiado elegante: ordenar principalmente por orden de ocurrencia, en segundo lugar por valor de carácter.

/:+/@(={:)\;"0]  Input is y.
          \      Map over prefixes:
  +/              Sum
    @(   )        of
      =           bit-array of equality
       {:         with last element.
                 This gives an array of integers whose i'th element is k
                 if index i is the k'th occurrence of y[i].
           ;     Pair this array
            "0   element-wise
              ]  with y
/:               and sort y using it as key.

Creo que puede guardar un byte moviendo la suma al exterior de los paréntesis `+ / @ (= {:)`
millas

@ Miles Oh sí, porque un tren tiene un rango infinito. ¡Genial gracias!
Zgarb

3

Mathematica, 55 bytes, no competitiva

(Sort@Characters@#//.{a___,b_,b_,c___}:>{a,b,c,b})<>""&

Editar: Desafortunadamente, Mathematica nosort es por códigos de caracteres, sino por orden alfabético, donde las mayúsculas siguen inmediatamente a las minúsculas ( es decir, se ordenan porHi There{ , e, e, h, H, i, r, T} ).

Esto funciona usando patrones:

//.{a___,b_,b_,c___}:>{a,b,c,b}
    a___       c___              (Three _) a zero or more members, named a and c
         b_,b_                   exactly one member, repeated twice (since they have the same name)
                    :>           Delayed Rule (replace left hand side with right hand side.)
                                 Delayed Rule evaluate on each substitution, avoiding conflicts with predefined variables
                      {a,b,c,b}  put one of the b-named member after all other sequences
//.                              repeat until no change (aka Replace Repeated)

1
Una cosa menor: Rule (->)debe ser RuleDelayed (:>)(sin cambios en el conteo de bytes) porque ambos lados de Ruletienen variables. Rulepuede causar conflictos con definiciones preexistentes. Por ejemplo: a=3;5/.{a_->a}devuelve 3, no 5. (se a_->aevalúa como a_->3si lo usa a_:>a, permanece así y a=3;5/.{a_:>a}regresa 5).
JungHwan Min

Marqué su respuesta como no competitiva porque no hace lo que especifica la pregunta (ordenar por código de caracteres, no en orden canónico).
JungHwan Min

@JungHwanMin arreglado a RuleDelayed. Gracias.
spacemit

2

Brainf * ck , 458 226 bytes

,[>>>>>>,]<<<<<<[[-<<<+<<<]>>>[>>>[>>>>>>]<<<[>>--[<->--]<-<[>->+<[>]>[<+>-]<<[<]>-]>>.[[-]<]<<<[[>>>>>>+<<<<<<-]<<<]>>>>>>]>>>[>>>[>>>>>>]<<<[>>--[<->--]<-<[>->+<[>]>[<+>-]<<[<]>-]>>[-<+<+>>]<[->>+<<]<[<<<<<<]>>>]>>>]]<<<<<<]

Pruébalo en línea! - BF

Numberwang , 262 226 bytes

8400000087111111442111911170004000400000071114002241202271214020914070419027114170270034427171114400000091111112711170000007000400040000007111400224120227121402091407041902711417027004219190071420091171411111170007000771111117

Pruébalo en línea! - NW

Puse ambos aquí porque son códigos idénticos.


2

PHP, 83 bytes

for($s=count_chars($argv[1]);$s=array_filter($s);$c%=128)echo$s[++$c]--?chr($c):'';

Desafortunadamente no puedes tenerlo unseten un ternario, así que necesito usar el molesto largo array_filter.
Usar como:

php -r "for($s=count_chars($argv[1]);$s=array_filter($s);$c%=128)echo$s[++$c]--?chr($c):'';" "If you sort a string you'll typically get something like:"

2

Python 2, 70 bytes

f=lambda s,i=0,c='':s[i>>7:]and(s.count(c)>i>>7)*c+f(s,i+1,chr(i%128))

Pruébalo en línea

Esto es muy ineficiente. El enlace de prueba cambia i>>7ai>>5 y establece el límite de recursividad a 10000. asume las entradas sólo tiene valores ASCII de hasta 126.

Utiliza el truco div-mod para iterar a través de dos bucles: recuentos mínimos i/128en el bucle externo y valores ASCII i%128en el bucle interno. Incluye un carácter ccon el valor ASCII dado si el número de veces que aparece en la cadena es al menos su recuento mínimo.

El código usa un truco para simular la asignación c=chr(i%128)para que pueda ser referenciada en la expresión (s.count(c)>i>>7)*c. Python lambdas no permite la asignación porque solo toman expresiones. La conversión a un defprograma completo o aún es una pérdida neta aquí.

En cambio, la función adelanta el valor chr(i%128)a la siguiente llamada recursiva como una entrada opcional. Esto está desactivado en uno porque ise ha incrementado, pero no importa siempre que la cadena no contenga caracteres especiales '\x7f'(también podríamos aumentar 128 a 256). La inicial c=''es inofensiva.


2

V , 37 36 bytes

¡Gracias @DJMcMayhem por el byte!

Í./&ò
dd:sor
Íî
òͨ.©¨±«©±À!¨.«©/±³²

Pruébalo en línea!

No estoy seguro de que me guste la expresión regular al final, pero necesitaba hacer el òdescanso de alguna manera.

Explique

Í./&ò                    #All chars on their own line
dd:sor                   #Delete empty line, sort chars
Íî                       #Join all lines together s/\n//
òͨ.©¨±«©±À!¨.«©/±³² #until breaking s/\v(.)(\1+)\1@!(.+)/\3\2\1

Íî(o :%s/\n//g) es más corto queVGgJ
DJMcMayhem

1

Perl 6 , 68 bytes

{my \a=.comb.sort;[~] flat roundrobin |a.squish.map({grep *eq$_,a})}

Me sorprendió un poco descubrir que no hay una forma integrada de agrupar elementos similares en una lista. Eso es lo que hace el bit squish-map.


1
Obtengo "Esta secuencia ya se ha iterado" a menos que cambie el nombre aa @a(+2 bytes). Además, grep *eq$_,se puede escribir grep $_,(-3 bytes) ya que una cadena es un emparejador inteligente válido.
sonríe el

1
{[~] flat roundrobin |.comb.classify(~*){*}.sort»[*]}- Esta variación es de solo 54 bytes.
sonríe el

@ Smis No veo ese error. Tal vez estamos usando diferentes versiones? Estoy en rakudo-star-2016.10. De todos modos, su solución avergüenza a la mía, debe publicarla como una respuesta separada.
Sean

Estoy usando un Rakudo de última generación compilado de la rama principal del repositorio de git esta semana. De todos modos, publiqué la classifysolución basada en una respuesta separada ahora.
sonríe el

1

JavaScript (ES6), 77 75 bytes

s=>(a=[],x={},[...s].sort().map(c=>a[x[c]=n=-~x[c]]=(a[n]||'')+c),a).join``

Estable ordena la cadena ordenada lexicográficamente por n th ocurrencia

F=s=>(a=[],x={},[...s].sort().map(c=>a[x[c]=n=-~x[c]]=(a[n]||'')+c),a).join``

const update = () => {
  console.clear();
  console.log(F(input.value));
};
input.oninput = update;
update();
#input {
  width: 100%;
  box-sizing: border-box;
}
<input id="input" type="text" value="         ':Iaaceeefggghiiiiklllllmnnooooprrssstttttuuyyyy" length=99/>
<div id="output"></div>


1+~~es el mismo que -~.
Neil

@Neil Awesome gracias -2 bytes
George Reith

1

Perl 6 , 54 bytes

{[~] flat roundrobin |.comb.classify(~*){*}.sort»[*]}

Explicación:

  • { }: Una lambda que toma un argumento, por ejemplo 21211 .
  • .comb: Divide el argumento de entrada en una lista de caracteres, p. Ej. (2,1,2,1,1) .
  • .classify(~*): Agrupe los caracteres utilizando la comparación de cadenas como la condición de agrupación, devolviendo un Hash desordenado, por ejemplo { 2=>[2,2], 1=>[1,1,1] }.
  • {*}: Devuelve una lista de todos los valores de Hash, por ejemplo [2,2], [1,1,1].
  • .sort: Ordenarlo, por ejemplo [1,1,1], [2,2].
  • »[*]: Pele los contenedores de elementos en los que se envolvieron las matrices debido a que están en el hash, para que no se consideren como un solo elemento en el siguiente paso, por ejemplo (1,1,1), (2,2).
  • roundrobin |: Comprime las sublistas hasta que se agoten todas, por ejemplo (1,2), (1,2), (1).
  • flat: Acoplar el resultado, por ejemplo 1, 2, 1, 2, 1.
  • [~]: Concatenarlo para obtener una cadena de nuevo, por ejemplo 12121.

(Crédito por el roundrobin enfoque va a la respuesta de Sean ).


1

05AB1E , 15 bytes

{.¡"ä"©¹g׫øJ®K

Pruébalo en línea! o como un conjunto de pruebas

Explicación

{                # sort input
 .¡              # group by equal elements
   "ä"©          # push "ä" and store a copy in the register
       ¹g×       # repeat the "ä" input-nr times
          «      # concatenate the result to each string in the grouped input
           ø     # zip
            J    # join to string
             ®K  # remove all instances of "ä" in the string

10 de los 15 bytes son para conocer la forma en que 05AB1E maneja cadenas de compresión de diferente longitud.


1

FSharp, 194 190 170 140 133 bytes

let f=Seq.map
let(@)=(>>)
f int@Seq.groupBy id@f(snd@Seq.mapi((*)128@(+)))@Seq.concat@Seq.sort@f((%)@(|>)128@byte)@Array.ofSeq@f char

Usar Seq en lugar de Array ahorra un par de bytes

Definir un nombre más corto y usar otros mapas para evitar (fun ->) bloqueo.

Resulta que F # puede asignar un carácter a una entrada, por lo que eliminar el nombre abreviado de System.Text.Encoding.ASCII y agregar otro mapa me ahorra 20 bytes.

Devolver una matriz de caracteres en lugar de una cadena, ¡me ahorra 30 bytes!

Ya no necesito asegurarme de que sea una cadena, me ahorra 7 bytes


0

JavaScript (ES6), 114 bytes

Separado con nueva línea para mayor claridad, no forma parte del recuento de bytes:

s=>[...s].map(a=>(m[a]=-~m[a])*128+a.charCodeAt(),m={})
.sort((a,b)=>a-b).map(a=>String.fromCharCode(a%128)).join``

Manifestación

`**Test cases:**
 *:Tacest*es*s*

If you sort a string you'll typically get something like:
 ':Iacefghiklmnoprstuy aegilnorstuy egilosty iloty lt    

Hello, World!
 !,HWdelorlol

#MATLAB, 114 bytes
 #,14ABLMTbesty 1A

f=@(s)[mod(sort(cell2mat(cellfun(@(c)c+128*(0:nnz(c)-1),mat2cell(sort(s),1,histc(s,unique(s))),'un',0))),128),''];
'()*+,-0128:;=@[]acdefhilmnoqrstuz'(),0128@acefilmnorstu'(),12celmnostu'(),12celnstu(),clnst(),cls(),cs(),()()()()`.split`\n\n`.map(s=>(p=s.split`\n`,console.log(`${p[0]}\n\n${r=f(p[0])}\n\nmatch: ${r==p[1]}`)),
f=s=>[...s].map(a=>(m[a]=-~m[a])*128+a.charCodeAt(),m={}).sort((a,b)=>a-b).map(a=>String.fromCharCode(a%128)).join``)


El mismo bytecount que mi código de Matlab, y exactamente el mismo enfoque. Sin embargo, aún no he intentado jugar al golf. Probablemente votaré más tarde si agregas una explicación :-) (He hecho un principio al no votar las respuestas sin explicaciones, incluso cuando lo entiendo) :-)
Stewie Griffin

0

Clojure, 79 bytes

#(for[V[(group-by(fn[s]s)%)]i(range 1e9)k(sort(keys V))c[(get(V k)i)]:when c]c)

Una función anónima, devuelve una secuencia de caracteres. Admite hasta 10 ^ 9 repeticiones de cualquier personaje, lo que debería ser suficiente.



0

Ruby, 59 + 1 = 60 bytes

Agrega un byte para la -nbandera. Puerto de la solución de diccionario @PatrickRoberts.

d={};print *$_.chars.sort_by{|c|d[c]||=0;c.ord+128*d[c]+=1}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.