Aufgabe
Wenn eine UTF-8-Zeichenfolge (mit allen Mitteln) angegeben wird, antworten Sie (mit allen Mitteln) auf eine äquivalente Liste, wobei jedes Element die Anzahl der Bytes ist, die zum Codieren des entsprechenden Eingabezeichens verwendet werden.
Beispiele
!
→ 1
Ciao
→ 1 1 1 1
tʃaʊ
→ 1 2 1 2
Adám
→ 1 1 2 1
ĉaŭ
→ 2 1 2
(einzelne Zeichen)
ĉaŭ
→ 1 2 1 1 2
(verwendet kombinierte Overlays)
チャオ
→ 3 3 3
(leere Eingabe) →
(leere Ausgabe)
!±≡𩸽
→ 1 2 3 4
(ein Null-Byte) → 1
Null Bytes
Wenn die einzige Möglichkeit, Eingaben über null Bytes hinaus zu lesen, darin besteht, die Gesamtanzahl der Bytes zu kennen, können Sie die Anzahl der Bytes auf beliebige Weise ermitteln (auch durch Benutzereingaben).
Wenn Ihre Sprache überhaupt keine Null-Bytes verarbeiten kann, können Sie davon ausgehen, dass die Eingabe keine Nullen enthält.
Antworten:
Pyth,
97 BytesVielen Dank an @Maltysen für das Speichern von 2 Bytes!
Testsuite
Wandelt jedes Zeichen der Eingabe in seine Binärdarstellung um und teilt diese dann in Abschnitte der Länge 8 auf. Die Anzahl dieser Abschnitte gibt dann die Anzahl der Bytes an, die zum Codieren dieses Zeichens erforderlich sind.
quelle
.E
Siemlhc8.B
ml%8.B
(jetztd
ist das implizit).Python 3,
4236 Bytesquelle
map
.lambda x:map(len,map(str.encode,x))
C
6865 BytesVielen Dank an @FryAmTheEggman für das Abschlagen von 3 Bytes!
Teste es auf Ideone .
quelle
APL, 15 Zeichen
In englischer Sprache: Konvertieren Sie jedes Zeichen in UTF-8 (was bedeutet: Vektor der Bytedarstellung) und erhalten Sie seine Abrechnung.
quelle
≢¨'UTF-8'∘⎕ucs¨
+⌿0 7 11 16∘.≤2⍟⎕UCS
0 7 11 16⍸2⍟⎕UCS
GolfScript, 16 Bytes
Probieren Sie es online!
Hintergrund
GolfScript hat keine Ahnung, was Unicode ist. Alle Zeichenfolgen (Eingabe, Ausgabe, intern) bestehen aus Bytes. Das kann zwar ziemlich ärgerlich sein, ist aber perfekt für diese Herausforderung.
UTF-8 codiert ASCII- und Nicht-ASCII-Zeichen unterschiedlich:
Alle Codepunkte unter 128 werden als codiert
0xxxxxxx
.Alle anderen Codepunkte werden als codiert
11xxxxxx 10xxxxxx ... 10xxxxxx
.Dies bedeutet, dass die Codierung jedes Unicode-Zeichens entweder ein einzelnes
0xxxxxxx
Byte oder ein einzelnes11xxxxxx
Byte und 1 bis 510xxxxxx
Bytes enthält.Indem wir alle Bytes der Eingabe durch 64 teilen , werden wir
0xxxxxxx
zu 0 oder 1 ,11xxxxxx
zu 3 und10xxxxxx
zu 2 .Wenn wir den Quotienten mit 2 vergleichen, drücken wir 1 für 2 ; und 0 für 0 , 1 und 3 - jedes Zeichen wird zu einer 0 , gefolgt von 1 bis 5 1 .
Alles , was übrig bleibt, ist die resultierende Zeichenfolge an Vorkommen von aufzuspalten 0 , zählen die Anzahl der 1 ‚s zwischen den Nullen und fügen Sie ein in die Menge.
Wie es funktioniert
quelle
PowerShell v4, 58 Byte
NB
OK, das sollte funktionieren und funktioniert in fast allen Testfällen, mit Ausnahme
𩸽
derer, die irgendwie als3,3
auf meinem Computer gezählt werden. Dieses Zeichen wird auf meinem Computer sogar als 7 Byte angezeigt. Ich vermute, dass dies an einem Fehler in der Windows- oder .NET-Version liegt, die ich lokal ausführe, da @Mego dieses Problem nicht hat . ( Edit: @cat weist darauf hin, dass dies an der Stückliste liegt . Vielen Dank für die Lösung dieses Rätsels, @cat! )Dies erklärt jedoch immer noch nicht das ganze Problem. Ich glaube jedoch zu wissen, woher einige der Probleme kommen. In .NET bestehen alle Zeichenfolgen aus UTF-16-Codeeinheiten (dies ist der Typ System.Char). Mit der sehr losen Typumwandlung, die von PowerShell verwendet wird, wird im Hintergrund viel implizites Casting und Konvertieren zwischen Typen durchgeführt. Wahrscheinlich ist dies ein Faktor, der zum Verhalten beiträgt, das wir beobachten. Beispielsweise werden
[system.text.encoding]::utf8.getchars([System.Text.UTF8Encoding]::UTF8.GetBytes('𩸽'))
zwei nicht druckbare Zeichen anstelle eines einzelnen Zeichens zurückgegeben.Erläuterung
Sehr einfacher Code. Nimmt die Eingabe
$args[0]
und wandelt sie explizit in ein Zeichen-Array um, damit wir jede Komponente des Strings durchlaufen können|%{...}
. Bei jeder Iteration verwenden wir den .NET-Aufruf[System.Text.Encoding]::UTF8.GetByteCount()
(derSystem.
impliziert ist), um die Byteanzahl des aktuellen Zeichens abzurufen$_
. Das ist in der Pipeline für die spätere Ausgabe platziert. Da es sich um eine Sammlung von[int]
s handelt, die zurückgegeben werden, ist das Umwandeln in ein Array implizit.Testläufe
Zum Hinzufügen bearbeitet Dies berücksichtigt die Null-Byte-Anforderung, die der Herausforderung nach dem ursprünglichen Posten hinzugefügt wurde, vorausgesetzt, Sie ziehen die Daten aus einer Textdatei und leiten sie wie folgt weiter:
quelle
That character even shows as 7 bytes on my computer.
Ja, das liegt an der Byte-Order Mark, die Sie unter Windows mit UTF-8 erhalten. Weisen Sie Notepad ++ an , die Stückliste zu verwendenUTF-8 without BOM
(da Sie die Stückliste insbesondere aus Gründen der Kompatibilität mit Unicies immer vermeiden sollten), und Sie werden feststellen, dass die Datei eine Größe von 4 Bytes hat, da die Stückliste 3 und 4 + 3 = 7 istget-content -Encoding UTF8 .\z.txt|%{.\bytes-per-character.ps1 $_}
weiterhin ausgeführt3,3
.-Encoding
Parameter scheint nicht unterstützt zu werden .JavaScript (ES6),
544543 ByteBearbeiten: 2 Bytes mit Hilfe von @ l4m2 gespeichert.
quelle
s=>[...s].map(c=>encodeURI(c).length/3-4&3)
Ruby, 33 Bytes
Verdrängt Python kaum, yay! Probieren Sie es online aus.
quelle
Perl 6 ,
77 6963 BytesDa Perl 6 NFG-Strings verwendet, muss ich die Bytes direkt einlesen, was die Funktion umgeht.
(NFG ähnelt NFC, es werden jedoch auch synthetisch zusammengesetzte Codepunkte erstellt.)
Die Ausgabe wird durch Zeilenumbrüche getrennt.
Prüfung:
Erläuterung:
Dies funktioniert, weil das erste Byte in einem Mehrbyte-Codepunkt die Anzahl der darin codierten Bytes aufweist und die anderen Bytes im Codepunkt das höchste gesetzte Bit haben, jedoch nicht das nächsthöhere. Während die Einzelbyte-Codepunkte nicht das höchste gesetzte Bit haben.
quelle
read:1
und / oder/while$
stattdessen? Und wenn das klapptif$
,?while
.\n1\n1\n
das beabsichtigt? Grundsätzlich behandelt dies NUL-Bytes?perl -e 'print "𩸽\0𩸽"' | perl6 -e '...'
bekomme ich414
genau das, was ich erwarten würde. (Der Teil über Nuls wurde hinzugefügt, nachdem ich allerdings gepostet habe)Python 3, 82 Bytes
Dies ist viel länger als die andere Python-Antwort und die meisten anderen Antworten, verwendet jedoch einen Ansatz mit Logarithmen, den ich noch nicht gesehen habe.
Eine anonyme Funktion, die Eingaben über Argumente als Zeichenfolge akzeptiert und eine Liste zurückgibt.
Probieren Sie es auf Ideone
Wie es funktioniert
Diese Methode basiert auf der Art und Weise, wie UTF-8 den Codepunkt eines Zeichens codiert. Wenn der Codepunkt kleiner als 128 ist, wird das Zeichen wie in ASCII codiert:
wo
x
repräsentiert die Bits des Codepunktes. Bei Codepunkten größer oder gleich 128 wird das erste Byte jedoch mit der gleichen Anzahl von1
s wie die Gesamtanzahl von Bytes aufgefüllt , und nachfolgende Bytes beginnen10
. Die Bits des Codepunkts werden dann eingegeben, um die kürzestmögliche Multibyte-Sequenz zu ergeben, und alle verbleibenden Bits werden0
.und so weiter.
Es kann nun bemerkt werden, dass für jede Anzahl von Bytes
n
die Obergrenze für die Anzahl von Codepunktbits durch gegeben ist(-n+7)+6(n-1) = 5n+1
. Daher wird der obere Grenzcodepunktc
für jedenn
in Dezimalzahl angegeben durchc= 2^(5n+1)
. Neuordnung gibt diesn = (log2(c)-1)/5
. Für jeden Codepunkt kann die Anzahl der Bytes ermittelt werden, indem der obige Ausdruck ausgewertet und dann die Obergrenze ermittelt wird.Dies funktioniert jedoch nicht für Codepunkte im Bereich
64 <= c <= 127
, da das Fehlen einer Auffüllung1
aufgrund der ASCII-ähnlichen Codierung für 1-Byte-Zeichen bedeutet, dass die falsche Obergrenze vorhergesagt wird undlog2
für undefiniert istc = 0
, was bei einem Null-Byte der Fall ist ist in der Eingabe vorhanden. Wenn alsoc <= 127
ein Wert von1
für n zurückgegeben wird.Genau das macht der Code. Für jedes Zeichen
i
in der Zeichenfolgex
wird der Codepunkt mithilfe derord
Funktion ermittelt, und die Obergrenze des Ausdrucks wird mithilfe einer Ganzzahl und nicht durch eine Gleitkommadivision dividiert5
und anschließend addiert1
. Da der Float-Typ von Python immerx.0
Ganzzahlen darstellt, wird das Ergebnis auch nach der Ganzzahldivision an dieint
Funktion übergeben, um die nachstehende Null zu entfernen. Wennord(i) <= 127
, bedeutet ein logischer Kurzschluss, dass er1
stattdessen zurückgegeben wird. Die Anzahl der Bytes für jedes Zeichen wird als Element in einer Liste gespeichert und diese Liste wird zurückgegeben.quelle
Java 10,
10096956761 Bytes-4 Bytes, die Leerzeichen entfernen, da dies in den Kommentaren zulässig ist
-1 Bytes, die
UTF-8
inutf8
-28 Bytes geändert werden und von Java 7 auf 8 (
a->{...}
anstelle vonvoid c(char[]i)throws Exception{...}
)-3 Bytes gehen, wobei die Eingabe als String-Array anstelle von Zeichenarray und
-3 Bytes verwendet wird von Java 8 auf 10 (
var
stattString
)Erläuterung:
Probieren Sie es online aus.
quelle
Julia, 34 Bytes
Dies ist eine anonyme Funktion, die eine Zeichenfolge akzeptiert und ein ganzzahliges Array zurückgibt. Um es aufzurufen, weisen Sie es einer Variablen zu.
Der Ansatz ist ganz einfach: Wenn die Eingabe leer ist, ist die Ausgabe leer. Andernfalls ordnen wir die
sizeof
Funktion, die die Anzahl der Bytes in einer Zeichenfolge zählt, jeder Teilzeichenfolge mit einem Zeichen zu.Probieren Sie es online! (beinhaltet alle Testfälle)
quelle
s->[sizeof("$c")for c=s]
spart ein paar Bytes.split("","")
nicht zurück[]
? (JavaScript"".split("")
tut es.)split("","")
scheint zu geben""
(im Gegensatz zu Python, das eine Ausnahme gibt), aber ich weiß nichts über die Kompatibilität von[]
und""
in Julia.split("", "") == [""]
dh ein Array mit einem Element, das eine leere Zeichenfolge enthält, aber das Problem ist dassizeof("") == 0
, was laut OP nicht zulässig ist.PHP,
9257 BytesAuf den zweiten Blick können Sie dies mit weniger Aufwand tun:
Probieren Sie es online aus. Beachten Sie, dass dies etwas länger dauert, da stdin anstelle eines Programmarguments verwendet wird.
Bei dieser Version müssen Sie an stderr gesendete Benachrichtigungen ignorieren, aber das ist in Ordnung .
alte version:
Verwendet einen etwas anderen Ansatz als die andere PHP-Antwort. Beruht auf der mangelnden nativen Unterstützung von Multibyte-Strings in PHP.
quelle
<?=
Emacs Lisp,
5549 BytesZerlegt zuerst die Zeichenfolge in eine Liste von Zeichen mit
(mapcar 'string s)
. Diestring
Funktion in Emacs Lisp erstellt aus einer Liste von Zeichen eine Zeichenfolge. Aufgrund der Art und Weise, wie Emacs Strings mitmapcar
(dh in eine Liste von Ganzzahlen, nicht Zeichen oder Strings) aufteilt, ist diese explizite Konvertierung erforderlich. Ordnet diestring-bytes
Funktion dann dieser Liste von Zeichenfolgen zu.Beispiel:
Testfälle:
Alte Antwort:Ungolfed:
Testfälle:
quelle
nil
wenn Sie das Ergebnis verflachen?nil
ist eine leere Liste (und die einzige Möglichkeit, in Emacs "falsch" zu sagen). Obwohl es in Emacs keine standardmäßige Abflachung gibt (Sie können dash's verwenden-flatten
), würde jede mögliche Implementierung diese beseitigen.JavaScript (Node), 27 Byte
Dies nimmt Eingaben als Array einzelner Zeichen und gibt ein Array von Byte-Zählern zurück.
Buffer
ist eine Methode zur Darstellung von binären Rohdaten. Buffer.byteLength (Zeichenfolge) gibt die Anzahl der Bytes in der Zeichenfolge an. UTF-8 ist die Standardkodierung. Beachten Sie, dass nur Node.js Puffer enthält, nicht Browser-JS. Das grobe Browser-Äquivalent heißt Blob und umfasst 31 Byte:Prüfung
Speichern Sie diese Datei, und führen Sie sie über den Knoten aus, oder versuchen Sie es online .
Dies sollte das Ergebnis sein:
quelle
Bash, 74 Bytes
Golf gespielt
Algorithmus
hexdump input string, falten Sie 2 Zeichen pro Zeile, schneiden Sie nur das erste Zeichen
(4 höherwertige Bits eines jeden Eingangsbytes als Hexadezimalzeichen, eines pro Zeile)
Entfernen Sie "Fortsetzungsbytes" 0x80..0xBF
(Was übrig bleibt, sind 4 Bits des ersten Bytes eines jeden Unicode-Zeichens.)
Ordne die ersten Bits der Zeichenlänge zu, reduziere die Ausgabe und drucke
Prüfung
quelle
-t
Option zutr
war mir unbekannt und ist anscheinend eine GNU-Erweiterung. Das Weiterleiten an die Befehlsersetzung nachecho
könnte auch eine etwas detailliertere Erklärung wert sein.PHP, 126 Bytes
Probieren Sie es online!
quelle
<?=($s=fgets(STDIN))?
C #
8982 BytesEin einfaches C # -Lambda, das die Zeichenfolge durchläuft und die durch Leerzeichen getrennte Liste zurückgibt.
Bearbeiten: 6 Bytes dank einiger sehr netter Kommentare gespeichert.
quelle
var J="";...
1121
und1 2 1 2
beide in Ordnung sind} return J;};
using System.Text
oder so - Importe sind nicht kostenlos.Haskell, 85 Bytes
quelle
map$...
Pyth, 17 Bytes
Probieren Sie es online!
Verwenden Sie den Code-Punkt der Zeichen mit einigen Arithmetik.
quelle
C 85 Bytes.
Untersucht die hohen 4 Bits jedes Bytes, um die Codierung und die Anzahl der nachfolgenden zu überspringenden Bytes zu bestimmen.
quelle
while *c
Exits in einer leeren Zeichenfolge, und das `c + = d 'überspringt Nullen in der Mitte eines Mehrbyte-Codepunkts.char*
wirklich) in C wird mit einem Null-Byte markiert. Es ist unmöglich, null Bytes vom tatsächlichen Ende der Zeichenfolge zu unterscheiden.Faktor
57878280 BytesErklärt:
Unit-Tests:
Sie gehen jetzt alle vorbei. c:
quelle
Swift 2.2,
675250 BytesSchrecklich hässlich. In Swift gibt es keine Möglichkeit, die UTF-8-Länge eines Zeichens zu ermitteln. Daher muss ich die Zeichenfolge nach Zeichen durchlaufen, das
Character
in ein umwandelnString
und dascount
eines einzelnen Zeichens suchenString
(hey, es ist zumindest ein integriertes Element vorhanden) Methode, um das zu tun). Suchen Sie nach Optimierungen, möglicherweise mit einem Scanner.Revision 1: 15 Bytes mit
count
anstelle von gespeichertunderestimateCount()
.Revision 2: Speichert weitere 2 Zeichen, indem für jeden Abschluss eine for-in-Schleife anstelle von a verwendet wird.
quelle
Rust, 53 Bytes
Rust hat utf-8-Zeichenprimitive, Iteratoren und Lambdas, das war also unkompliziert. Testcode:
Ausgänge
quelle
jq, 26 Zeichen
(23 Zeichen Code + 3 Zeichen Befehlszeilenoption)
Hoffentlich im Wettbewerb. Obwohl
utf8bytelength
es 9 ++ Monate vor dieser Frage hinzugefügt wurde , ist es immer noch nicht in der veröffentlichten Version enthalten.Probelauf:
quelle
C (gcc) , 53 Bytes
Probieren Sie es online!
quelle
SmileBASIC, 69 Bytes
Die Eingabe ist ein Array von Bytes.
Die Anzahl der Bytes in einem UTF-8-Zeichen entspricht der Anzahl der führenden
1
Bits im ersten Byte (es sei denn, es gibt keine1
s, in diesem Fall ist das Zeichen 1 Byte). Um die Anzahl der führenden Einsen zu ermitteln, sucht das Programm die erste0
in der Binärdarstellung und addiert 1, wenn dies 0 war.quelle
F #,
595466 BytesTechnisch gesehen ist s eine Zeichenfolge, aber es stellt sich heraus, dass es eine implizite Konvertierung gibt, mit der ein String übergeben werden kann.
Wenn Sie dies in der Konsole mit testen
!±≡𩸽
, wird das Kanji in zwei Zeichen mit einer Länge von jeweils 3 Byte aufgeteilt. Alle anderen Testfälle funktionieren einwandfrei.Bearbeiten: Es stellt sich heraus, dass allgemeine Namespace-Importe nicht implizit sind. Noch 12 Zeichen.
quelle
UTF-8 without BOM
ist, ist dies falsch und sollte behoben werden. 3) Wie es scheint, braucht F # Aussagen , die wie SMLlet f(x)= ...
enden;;
. 4) Sie können aufhören, dieser anonymen Funktion einen Namen zuzuweisen, d(s)=seq{for c in s->Encoding.UTF8.GetByteCount([|c|])}
. H.error FS0039: The namespace or module 'Encoding' is not defined
beim Versuch, dies auszuführen. Was mache ich falsch?System.Text
Namespace öffnen . Ich gehe davon aus, dass der Namespace geöffnet wird und der Eintragscode aus AstroDans C # -Antwort enthalten ist.import
,#include
,open
,load
,require
,using
,USING:
etc hier auf PPCG. AstroDans C # -Antwort ist ebenfalls falsch, und ich habe sie darüber informiert.05AB1E , 15 Bytes
Probieren Sie es online aus.
Die Kopfzeile
ε
wird verwendet, um alle Testfälle einzeln zu bearbeiten.Fußzeile
ï]J]»
zum hübschen Ausdrucken der ausgegebenen Zeichenlisten (ï
: Dezimalstellen und Zeichen in Ganzzahlen;:]
Schließen von if-else und for-each;:Verbinden vonJ
Ziffern}
;: Schließen des Headers foreach;:»
Verbinden durch neue Zeilen).Erläuterung:
Da 05AB1E keine eingebauten Funktionen zum Konvertieren von Zeichen in die Anzahl der verwendeten Bytes hat,
Ç
konvertiere ich die Zeichen in ihre Unicode-Werte. In einem For- Each-Verfahren wird im Pseudocode Folgendes ausgeführt:Inspiriert von @TheBikingVikings Python 3 Antwort .
quelle
Zsh , 41 Bytes
Probieren Sie es online!
Zsh ist UTF-8-fähig, daher teilen wir die Zeichenfolge in Zeichen auf, deaktivieren Multibyte und drucken die Länge der einzelnen Zeichen.
quelle