Подсчитать байты программы


21

Примечание 2: я принял @DigitalTrauma6-байтовый длинный ответ. Если кто-то может победить, я изменю принятый ответ. Спасибо за игру!

Примечание: я приму ответ в 6:00 вечера MST 14.10.15. Спасибо всем, кто участвовал!

Я очень удивлен тем, что об этом еще не спрашивали (или я не достаточно усердно искал). В любом случае, эта задача очень проста:

Ввод: программа в виде строки. Кроме того, входные данные могут содержать или не содержать:

  • Ведущие и конечные пробелы
  • Замыкающие переводы
  • Не-ASCII символы

Вывод: два целых числа, одно из которых представляет количество символов UTF-8, а другое представляет количество байтов, вы можете выбрать, в каком порядке. Конечные переводы строки разрешены. Вывод может быть в STDOUT или возвращен из функции. Это может быть в любом формате, если эти два числа различимы (2327 не является допустимым выводом).

Заметки:

Пример ввода / вывода: (Все выходы в форме {characters} {bytes})

Входные данные: void p(int n){System.out.print(n+5);}

Выход: 37 37

Входные данные: (~R∊R∘.×R)/R←1↓ιR

Выход: 17 27

Входные данные:


friends = ['john', 'pat', 'gary', 'michael']
for i, name in enumerate(friends):
    print "iteration {iteration} is {name}".format(iteration=i, name=name)

Выход: 156 156

Это код гольфа - выигрывает самый короткий код в байтах !

Leaderboards

Вот фрагмент стека, который генерирует как регулярную таблицу лидеров, так и обзор победителей по языкам.

Чтобы убедиться, что ваш ответ обнаружен, начните его с заголовка, используя следующий шаблон уценки:

# Language Name, N bytes

где Nразмер вашего представления. Если вы улучшите свой счет, вы можете сохранить старые результаты в заголовке, вычеркнув их. Например:

# Ruby, <s>104</s> <s>101</s> 96 bytes

Если вы хотите включить в заголовок несколько чисел (например, потому что ваш результат равен сумме двух файлов или вы хотите перечислить штрафы за флаг интерпретатора отдельно), убедитесь, что фактический результат является последним числом в заголовке:

# Perl, 43 + 2 (-p flag) = 45 bytes

Вы также можете сделать название языка ссылкой, которая затем будет отображаться во фрагменте списка лидеров:

# [><>](http://esolangs.org/wiki/Fish), 121 bytes

var QUESTION_ID=60733,OVERRIDE_USER=36670;function answersUrl(e){return"http://api.stackexchange.com/2.2/questions/"+QUESTION_ID+"/answers?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+ANSWER_FILTER}function commentUrl(e,s){return"http://api.stackexchange.com/2.2/answers/"+s.join(";")+"/comments?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+COMMENT_FILTER}function getAnswers(){jQuery.ajax({url:answersUrl(answer_page++),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){answers.push.apply(answers,e.items),answers_hash=[],answer_ids=[],e.items.forEach(function(e){e.comments=[];var s=+e.share_link.match(/\d+/);answer_ids.push(s),answers_hash[s]=e}),e.has_more||(more_answers=!1),comment_page=1,getComments()}})}function getComments(){jQuery.ajax({url:commentUrl(comment_page++,answer_ids),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){e.items.forEach(function(e){e.owner.user_id===OVERRIDE_USER&&answers_hash[e.post_id].comments.push(e)}),e.has_more?getComments():more_answers?getAnswers():process()}})}function getAuthorName(e){return e.owner.display_name}function process(){var e=[];answers.forEach(function(s){var r=s.body;s.comments.forEach(function(e){OVERRIDE_REG.test(e.body)&&(r="<h1>"+e.body.replace(OVERRIDE_REG,"")+"</h1>")});var a=r.match(SCORE_REG);a&&e.push({user:getAuthorName(s),size:+a[2],language:a[1],link:s.share_link})}),e.sort(function(e,s){var r=e.size,a=s.size;return r-a});var s={},r=1,a=null,n=1;e.forEach(function(e){e.size!=a&&(n=r),a=e.size,++r;var t=jQuery("#answer-template").html();t=t.replace("{{PLACE}}",n+".").replace("{{NAME}}",e.user).replace("{{LANGUAGE}}",e.language).replace("{{SIZE}}",e.size).replace("{{LINK}}",e.link),t=jQuery(t),jQuery("#answers").append(t);var o=e.language;/<a/.test(o)&&(o=jQuery(o).text()),s[o]=s[o]||{lang:e.language,user:e.user,size:e.size,link:e.link}});var t=[];for(var o in s)s.hasOwnProperty(o)&&t.push(s[o]);t.sort(function(e,s){return e.lang>s.lang?1:e.lang<s.lang?-1:0});for(var c=0;c<t.length;++c){var i=jQuery("#language-template").html(),o=t[c];i=i.replace("{{LANGUAGE}}",o.lang).replace("{{NAME}}",o.user).replace("{{SIZE}}",o.size).replace("{{LINK}}",o.link),i=jQuery(i),jQuery("#languages").append(i)}}var ANSWER_FILTER="!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe",COMMENT_FILTER="!)Q2B_A2kjfAiU78X(md6BoYk",answers=[],answers_hash,answer_ids,answer_page=1,more_answers=!0,comment_page;getAnswers();var SCORE_REG=/<h\d>\s*([^\n,]*[^\s,]),.*?(\d+)(?=[^\n\d<>]*(?:<(?:s>[^\n<>]*<\/s>|[^\n<>]+>)[^\n\d<>]*)*<\/h\d>)/,OVERRIDE_REG=/^Override\s*header:\s*/i;
body{text-align:left!important}#answer-list,#language-list{padding:10px;width:290px;float:left}table thead{font-weight:700}table td{padding:5px}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <link rel="stylesheet" type="text/css" href="//cdn.sstatic.net/codegolf/all.css?v=83c949450c8b"> <div id="answer-list"> <h2>Leaderboard</h2> <table class="answer-list"> <thead> <tr><td></td><td>Author</td><td>Language</td><td>Size</td></tr></thead> <tbody id="answers"> </tbody> </table> </div><div id="language-list"> <h2>Winners by Language</h2> <table class="language-list"> <thead> <tr><td>Language</td><td>User</td><td>Score</td></tr></thead> <tbody id="languages"> </tbody> </table> </div><table style="display: none"> <tbody id="answer-template"> <tr><td>{{PLACE}}</td><td>{{NAME}}</td><td>{{LANGUAGE}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody> </table> <table style="display: none"> <tbody id="language-template"> <tr><td>{{LANGUAGE}}</td><td>{{NAME}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody> </table>


делает вывод должен быть разделен пробелом?
Maltysen

нет, он может быть в любом формате, если числа различимы (2327 - недопустимый вывод)
GamrCorps

Разве нет символов UTF-8, которые в зависимости от интерпретации можно разделить на два других символа, которые генерируют одинаковые байтовые значения? Как мы их посчитаем?
Патрик Робертс

Честно говоря, я не знаю, что вы имеете в виду. Поэтому считай как хочешь.
GamrCorps

@GamrCorps Символы UTF-8 включают не-ASCII символы, которые в основном являются символами, которые не могут быть представлены одним байтом, но должны быть представлены двумя или даже четырьмя байтами. В зависимости от того, как символы считываются программой, программа сама выбирает, как интерпретировать поток байтов. Например, 2-байтовый UTF-8 может интерпретироваться как 2 последовательных символа ASCII, каждый из которых представлен двумя байтами, составляющими первоначально предназначенный символ.
Патрик Робертс

Ответы:


32

Shell + coreutils, 6

Этот ответ становится недействительным, если используется кодировка, отличная от UTF-8.

wc -mc

Тестовый вывод:

$ printf '%s' "(~R∊R∘.×R)/R←1↓ιR" | ./count.sh 
     17      27
$ 

В случае строгого применения выходного формата (только один пробел, разделяющий два целых числа), мы можем сделать это:

Shell + coreutils, 12

echo`wc -mc`

Спасибо @immibis за предложение удалить пробел после echo . Мне потребовалось некоторое время, чтобы понять это - оболочка расширит это до echo<tab>n<tab>m, и вкладки по умолчанию будут включены $IFS, поэтому в полученной команде совершенно допустимы разделители токенов.


13
Определенно правильный инструмент для работы.
Алекс А.

1
Вы можете удалить пробел после "эха"?
user253751 14.10.15

@immibis Да - хорошо - я не мог сразу увидеть, как это сработало.
Цифровая травма

21

GolfScript, 14 12 байт

.,p{64/2^},,

Попробуйте это онлайн на Web GolfScript .

идея

GolfScript не знает, что такое Unicode; все строки (входные, выходные, внутренние) состоят из байтов. Хотя это может быть довольно раздражающим, но оно идеально подходит для этой задачи.

UTF-8 по-разному кодирует символы ASCII и не-ASCII:

  • Все кодовые точки ниже 128 кодируются как 0xxxxxxx.

  • Все остальные кодовые точки кодируются как 11xxxxxx 10xxxxxx ... 10xxxxxx.

Это означает, что кодировка каждого символа Unicode содержит либо один 0xxxxxxxбайт, либо один 11xxxxxxбайт (и от 0 до 5 10xxxxxxбайтов).

Разделив все байты ввода на 64 , мы превращаемся 0xxxxxxxв 0 или 1 , 11xxxxxxв 3 и 10xxxxxxв 2 . Осталось только посчитать байты, у которых не 2 .

Код

                (implicit) Read all input and push it on the stack.
.               Push a copy of the input.
 ,              Compute its length (in bytes).
  p             Print the length.
   {     },     Filter; for each byte in the original input:
    64/           Divide the byte by 64.
       2^         XOR the quotient with 2.
                If the return is non-zero, keep the byte.
           ,    Count the kept bytes.
                (implicit) Print the integer on the stack.

9

Python, 42 40 байт

lambda i:[len(i),len(i.encode('utf-8'))]

Спасибо Алексу А. за два байта.

Просто, делает то, что говорит. С аргументом iпечатает длину i, затем длину iв UTF-8. Обратите внимание , что для того , чтобы принять многострочный ввод, аргумент функции должен быть окружен тройными кавычками: '''.

РЕДАКТИРОВАТЬ: Это не сработало для многострочного ввода, поэтому я просто сделал это вместо функции.

Некоторые тестовые случаи (разделенные пробелами):

f("Hello, World!")
13 13

f('''
friends = ['john', 'pat', 'gary', 'michael']
for i, name in enumerate(friends):
    print "iteration {iteration} is {name}".format(iteration=i, name=name)
''')
156 156

f("(~R∊R∘.×R)/R←1↓ιR")
17 27

И вот все это время я использовал просто len () как присоску. Это явно выше.
Статус

3
Поскольку выходные данные могут быть возвращены из функции, вы можете сохранить несколько байтов, сделав это lambda i:[len(i),len(i.encode('utf-8'))].
Алекс А.

@AlexA. Хорошо, меняется. Никогда не трогал лямбду раньше.
The_Basset_Hound

1
Ваша лямбда не совсем правильно сформирована. Если вы дадите ему определение, оно будет f=lambda i:[len(i),len(i.encode('utf-8'))], но поскольку вы используете анонимную лямбда-функцию, это должно быть просто так lambda i:[len(i),len(i.encode('utf-8'))].
Каде

1
Вы можете сохранить несколько байтов U8вместоutf-8 .
Мего

5

Юлия, 24 байта

s->(length(s),sizeof(s))

Это создает лямбда-функцию, которая возвращает кортеж целых чисел. lengthФункция, при вызове на строку, возвращает количество символов. sizeofФункция возвращает число байт во входных данных.

Попробуйте онлайн



3

Pyth - 12 9 байт

Постараюсь стать короче.

lQh/l.BQ8

Тестовый пакет .


Это дает слишком много байтов для счетчика байтов UTF-8. Это в настоящее время floor(… / 8) + 1, должно бытьceil(… / 8)
PurkkaKoodari

Это помогло мне поймать ошибку .B. Также lQlc.BQ8исправляет ошибку, о которой упоминает Pietu1998 при сохранении 1 байта, я думаю.
Исаак

3

Java, 241 90 89 байт

int[]b(String s)throws Exception{return new int[]{s.length(),s.getBytes("utf8").length};}

Очень нравится, что у вас есть Java до 100 байт.
GamrCorps

Ну, это всего лишь метод ...
SuperJedi224

1
Вы можете изменить getBytes("UTF-8")на getBytes("utf8"). А почему throws Exception?
RAnders00

Потому что getBytes выбрасывает, UnsupportedEncodingExceptionкогда вы даете ему неверное имя кодировки.
SuperJedi224



2

R, 47 байт

a<-commandArgs(TRUE);nchar(a,"c");nchar(a,"b")

Входные данные: (~R∊R∘.×R)/R←1↓ιR

Выход:

[1] 17
[2] 27

Если печать строк рядом с выводом не разрешена в «любом формате», то cat можно решить проблему:

R, 52 байта

a<-commandArgs(TRUE);cat(nchar(a,"c"),nchar(a,"b"))

Входные данные: (~R∊R∘.×R)/R←1↓ιR

Выход: 17 27


Как функция, 39 байтов:function(s)c(nchar(s,"c"),nchar(s,"b"))
Алекс А.

1
Кроме того, только некоторые советы гольф общего R: Вы можете использовать Tвместо TRUE, =вместо <-, и вход может поступать из scan, readlineили function, все из которых короче commandArgs.
Алекс А.

1

Млечный Путь 1.6.2 , 7 байт (неконкурентный)

':y!^P!

объяснение

'        ` read input from the command line
 :       ` duplicate the TOS
  y      ` push the length of the TOS
   !  !  ` output the TOS
    ^    ` pop the TOS
     P   ` push the length of the TOS in bytes

использование

./mw <path-to-code> -i <input>

Я отметил это как не конкурирующее, так как проблема предшествует языку.
Mego


1

Brainfuck, 163 байта

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

С разрывами строки для удобства чтения:

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

Самая важная часть - первая строка. Это подсчитывает количество введенных символов. Остальное - просто длинный мусор, необходимый для печати числа больше 9.

РЕДАКТИРОВАТЬ: Поскольку BF не может вводить / выводить ничего, кроме ASCII чисел от 1-255, не было бы никакого способа измерить символы UTF-8.


Похоже, что это может быть больше в гольфе. Но, вероятно, не может. +1.
wizzwizz4

0

пчелиный воск, 99 87 байт

Более компактная версия, на 12 байт короче первой:

p~5~q")~4~p")~7~g?<
>)'qq>@PPq>@Pp>Ag'd@{
     >@PPPq  @dNp"?{gAV_
     >@PPPP>@>?b>N{;

Так же, как проще следовать гексагональной раскладке:

 p ~ 5 ~ q " ) ~ 4 ~ p " ) ~ 7 ~ g ? <
> ) ' q q > @ P P q > @ P p > A g ' d @ {
         > @ P P P q     @ d N p " ? { g A V _ 
        > @ P P P P > @ > ? b > N { ;

Выход , как characters, затем bytecount, разделенные символом новой строки.

Пример: маленькая буква sв начале строки просто говорит пользователю, что программа хочет вводить строку.

julia> beeswax("utf8bytecount.bswx")
s(~R∊R∘.×R)/R←1↓ιR
17
27
Program finished!

Пример пустой строки:

julia> beeswax("utf8bytecount.bswx")
s
0
0
Program finished!

Пчелиный воск выталкивает символы строки, введенной в STDIN, в глобальный стек, закодированный как значения их кодовых точек Unicode.

Для облегчения понимания ниже приведена развернутая версия программы:

             >@{;    >@P@p >@PP@p>@P p
_VAg{?"pN>Ag"d?g~7~)"d~4~)"d~5~)"d@PPp
    ;{N< d?              <      < @PP<

В этом примере символ αвводится в STDIN (код точки U+03B1, десятичном: 945)

                                        gstack     lstack

_VA                                     [945,1]•   [0,0,0]•    enter string, push stack length on top of gstack
   g                                               [0,0,1]•    push gstack top value on top of local stack (lstack)
    {                                                          lstack 1st value to STDOUT (num. of characters)
     ?                                  [945]•                 pop gstack top value
      "                                                        skip next if lstack 1st >0
        N>                                                     print newline, redirect to right
          Ag                            [945,1]•   [0,0,1]•    push gstack length on top of gstack, push that value on lstack.
            "                                                  skip if lstack 1st > 0
              ?                         [945]•                 pop gstack top value
               g                                   [0,0,945]•  push gstack top value on lstack
                ~                                  [0,945,0]•  flip lstack 1st and 2nd
                 7                                 [0,945,7]•  lstack 1st=7
                  ~                                [0,7,945]•  flip lstack 1st and 2nd
                   )                               [0,7,7]•    lstack 1st = lstack 1st >>> 2nd  (LSR by 7)
                    "                                          skip next if top >0
                      ~4~)                         [0,0,0]•            flip,1st=4,flip,LSR by 4
                          "d                                   skip next if top >0... redirect to upper right
                           >@                                  redirect to right, flip lstack 1st and 3rd
                             PP@                   [2,0,0]•    increment lstack 1st twice, flip 1st and 3rd
                                p                              redirect to lower left
                                "                              (ignored instruction, not relevant)
         d?              <      <       []•                       redirect to left... pop gstack, redirect to upper right

         >Ag"d                          [0]•       [2,0,0]•    redir. right, push gstack length on gstack
                                                               push gstack top on lstack, skip next if lstack 1st > 0
                                                               redir. to upper right.
         >@                                        [0,0,2]•    redir right, flip lstack 1st/3rd
           {;                                                  output lstack 1st to STDOUT, terminate program

По сути, эта программа проверяет каждое значение кодовой точки на предмет ограничений на 1-байтовую, 2-байтовую, 3-байтовую и 4-байтовую кодовую точку.

Если nэто значение кодовой точки, то эти ограничения для правильных строк UTF-8:

codepoint 0...127         1-byte: n>>>7 = 0
          128...2047      2-byte: n>>>11= 0  → n>>>7>>>4
          2048...65535    3-byte: n>>>16= 0  → n>>>7>>>4>>>5
          65535...1114111 4-byte: the 3 byte check result is >0

Вы можете найти номера 7, 4и 5для команд сдвига в коде выше. Если проверка 0завершается, счетчик lstack увеличивается соответствующим образом, чтобы подсчитать количество байтов введенной строки. В @PP...@конструкции увеличить счетчик байтов. После каждого подсчета самая верхняя точка Unicode выталкивается из gstack, пока она не станет пустой. Затем счетчик байтов выводится в STDOUT и программа завершается.

Нет никаких проверок на неправильное кодирование, такое как слишком длинное кодирование ASCII и недопустимые кодовые точки 0x10FFFF, но я думаю, это нормально;)


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.