Сортуйте символи за темрявою


38

Ваша програма повинна приймати як введення рядок символів, як це:

@+.0

І виведіть символів, відсортованих за темністю, на якій вони темні:

.+0@

Вимоги:

  • Для виявлення темряви потрібно використовувати односхилий шрифт.

  • Ви повинні дізнатися, скільки пікселів займає кожен символ. Ви дійсно повинні намалювати символи та порахувати пікселі, тобто ви не можете просто розмістити пікселі у жорсткому коді.

    • Як конкретніше правило: якщо ви переключили шрифти, програма все одно повинна працювати. Крім того, ваша програма повинна мати можливість перемикати шрифти, просто змінюючи змінну або значення або рядок у коді.
  • Якщо ви використовуєте антиаліасинг, ви повинні рахувати пікселі як відсотки від повністю чорного пікселя. Наприклад, rgb(32, 32, 32)піксель вважатиметься 1/8 повного пікселя. Нехтуйте цим правилом, якщо ваші персонажі не захищені.

  • Після підрахунку пікселів необхідно сортувати символи за кількістю пікселів та виводити їх у порядку.

  • Це , тому найкоротший код у байтах виграє.


7
Як не дивно, це також підходить для RPG.se!
corsiKa

1
Що, ніякої корекції для відображення гамми в розрахунку темряви?
Ільмарі Каронен

6
Чи можемо ми використовувати білий шрифт? Якщо так, то я думаю, що це я завернув.
Павло

Відповіді:


22

Mathematica, 112 110 108 байт

Це все ще може бути гольф далі. Припускає, що рядок знаходиться в змінній s.

А тепер використовує правильний синтаксис для сортування одного списку за іншим списком.
Щасливі тестові справи -> "О так, це працює" -> Facepalm
Спасибі за гострі очі, Девід Карраер.

Оновлення: Замінив OCR A на Menlo, тому що я зрозумів, що на OSX прізвище шрифту OCR A насправді OCR A Std. Тому я сортував шрифт за замовчуванням замість реальної угоди. Менло також одномісний з таким же числом байтів, так що чистий прибуток чи втрати не мають.

Я виставив розміщений експорт ноутбука CDF , тож ви можете побачити код у дії, якщо хочете. Я досі розгадую, як додати деяку інтерактивність до веб-розміщених CDF, тому поки що це просто статично.

c=Characters@s;Last/@Sort[Transpose@{Total[1-#&/@ImageData@Rasterize@Style[#,FontFamily->"Menlo"],3]&/@c,c}]

Вихід для s = FromCharacterCode /@ Range[33, 135];"Кур'єр"

введіть тут опис зображення

Вихід для того ж, але з FontFamily "Monospace":

введіть тут опис зображення

Зауважте, що кінцеві результати відображаються у внутрішньому шрифті MM, а не в сортованому шрифті. Отже, ви бачите відмінності у вибраному шрифті, відображеному у сортуванні. Хоча посилання CDF показує і те, і інше, для комплексистів.

Невикористаний код:

s = FromCharacterCode /@ Range[33, 135];
c = Characters@s;
Last /@ Sort[
    Transpose@{Total[1 - # & /@ 
        ImageData@Rasterize@Style[#, FontFamily -> "Menlo"], 3] & /@ c, c}]

1
Вивчіть цей вклад:"" <> (FromCharacterCode /@ Range[33, 135])
DavidC

Сім'я за замовчуванням чи ні, специфікації вимагають "ваша програма повинна мати можливість перемикати шрифти, просто змінюючи змінну". Через значення згладжування можна отримати деякі види, які виглядають неправильно, але я ще раз перегляну повний діапазон і побачу, чи щось не так.
Джонатан Ван Матре

1
яка жахлива мова! щойно дізнався про нові зусилля з мови програмування Вольфрамом днями, з нетерпінням чекаючи цього.
the0ther

1
Ви можете зберегти два байти, змінивши символи [] на символи @ та назад [] на зворотні @.
Майкл Стерн

2
Я не хочу розміщувати подібну відповідь, але я спробував себе, і це вийшло коротшеStringJoin@SortBy[Characters@"@+.0",ImageData@Binarize@Rasterize@Style[#,FontFamily->"Monospace"]~Total~2&]
швейцарський

25

Bash + ImageMagick: 164 147 148 символів

while read -n1 c
do
o=`convert -size 20x15 xc: +antialias -font cour.ttf -draw "text 0,10 '$c'" xpm:-`
o=${o//[^ ]}
a[${#o}]+=$c
done
echo "${a[@]}"

Проба зразка:

bash-4.1$ echo -n '@+.0' | bash graysort.sh
. + 0 @

Між групами сірості вставляються роздільники. Символи з однаковим рівнем сірості не відокремлюються:

bash-4.1$ echo -n 'abcdefghijklmnopqrstuvwxyz' | bash graysort.sh
i cl jortz esv ax u df bgnpq y hk w m

+1 для сортування за допомогою індексів масиву bash замістьsort
Digital Trauma

9

QBasic, 259 байт

SCREEN 1
DIM a(255)
FOR i = 32 TO 255
    CLS
    PRINT CHR$(i);
    FOR p = 0 TO 64
        a(i) = a(i) + POINT(p MOD 8, p \ 8)
    NEXT p
NEXT i
FOR p = 0 TO 96
    FOR i = 32 TO 255
        IF a(i) = p THEN PRINT CHR$(i);
    NEXT i
NEXT p

Я робив це заради забави, тому технічно це не відповідає правилам в один спосіб. Він не приймає список символів, але натомість друкує всі символи з 32-255 і використовує це замість цього. Якщо ви дійсно хочете побачити версію, яка відповідає цьому правилу, будь ласка, скажіть мені.

Він також не відповідає іншій техніці: "Крім того, ваша програма повинна мати можливість перемикати шрифти, просто змінюючи змінну або значення або рядок у коді." Немає простого способу зробити це з QBasic. Однак програма, звичайно, буде добре працювати з будь-якою кодовою сторінкою на ваш вибір.

Нарешті, я міг видавити кілька символів (переважно пробіл, який QBasic IDE корисно вставляє), але, мабуть, цього не варто, оскільки ця відповідь не має шансів виграти в будь-якому випадку.

QBasic сортує персонажів за темрявою


Плюс один для того, щоб це зробити для розваги!
Джонатан Ван Матре

8

Javascript + Полотно та браузер DOM ( 280 237 235 байт)

Оновлена ​​версія з пропозиціями Fors та зубною щіткою у коментарях:

function m(x){a=document.createElement('canvas').getContext('2d');a.font='9px Monaco';a.fillText(x,y=i=0,20);for(;i<3600;)y+=a.getImageData(0,0,30,30).data[i++];return y}alert(s.split('').sort(function(a,b){return m(a)-m(b)}).join(''))

Більш прочитана версія:

// Scoring function - Calculates darkness for single character
function m(x) {
    a = document.createElement('canvas').getContext('2d');
    a.font = '9px Monaco';
    a.fillText(x, y = i = 0, 20);
    for (; i < 3600;) y += a.getImageData(0, 0, 30, 30).data[i++];
    return y
}
// Assume input is in variable s and alert as output. Comparison function now expression.
alert(s.split('').sort(function (a, b) {
    return m(a) - m(b)
}).join(''))

Можливо, можна більше пограти в гольф.

Я новачок на цьому веб-сайті, тому я не впевнений, як зазвичай вводиться інформація для відповідей на Javascript. Я припускаю, що вхід міститься в змінній з назвою s. Якщо це не в порядку, я оновлю відповідь та кількість символів.

JSFiddle оновленої версії.

JSFiddle першої версії .


Мені це дуже подобається, проте тут є багато можливих удосконалень. Змінні cі sнепотрібні ( a=document.createElement('canvas').getContext('2d')і y+=a.getImageData(0,0,30,30).data[i]), елемент не потрібно додавати, нульова ініціалізація yможе бути поєднана з такою i( i=y=0), післязростання iможе поєднуватися з додаванням y( for(...;y+=...[i++]);) і шрифту Монако є монорозміщеним і має коротше ім'я, ніж Кур'єр.
Форс

Спасибі! Я ще не досвідчений гольфіст, тому ваші коментарі дуже допомагають. Зараз я їх включив у код.
віск

Тут відповіді Javascript зазвичай читаються вхідними даними prompt(); але це теж добре.
Картик

Ви можете видалити y=i=0;та змінити a.fillText(x,0,20)на a.fillText(x,y=i=0,20).
Зубна щітка

Дякую, додав і це! Два символи - це два символи!
віск

3

PHP, 298 символів

Я додав кілька перерв рядків, щоб ви могли бачити це у всій його огидності:

<?php
$s=@$_GET[s];$a=array();$v=imagecreate(16,16);$f='imagecolorallocate';
$f($v,0,0,0);for($i=0;$i<strlen($s);$i++){$c=$f($v,$i,0,1);
imagechar($v,5,2,$n=0,$s[$i],$c);for($y=16;$y--;)
for($x=16;$x--;)$n+=($c==imagecolorat($v,$x,$y));
$a[]=ord($s[$i])+($n<<8);}sort($a);foreach($a as $v)echo chr($v);

Цей код використовує шрифти GD, які вбудовані разом із PHP. Другий аргумент imagechar()вибору шрифту (цифри від 1 до 5 є дійсними).

Приклад:

Input:  !@#$%^&*-=WEIX,./'
Output: '-.,^=!/*IE%X#$&@W

Якщо ви вставите наступне поверх коду, показаного вище, ви зможете надати список символів у своєму веб-браузері.

<?php
define("FONT_SIZE",5);
if(@$_SERVER['PATH_INFO']=='/a.png') {
  $s = $_GET['s'];
  $im = imagecreate(strlen($s)*(FONT_SIZE+4)+4,FONT_SIZE+12);
  imagecolorallocate($im,255,255,128);
  $c = imagecolorallocate($im,0,0,0);
  imagestring($im,FONT_SIZE,2,0,$s,$c);
  header("Content-Type: image/png");
  imagepng($im);
  imagedestroy($im);
  exit();
}
$me = $_SERVER['PHP_SELF'];
$t1 = $img = "";
if ($t1=htmlspecialchars(@$_GET['s'])) {
  $t2=urlencode($_GET['s']);
  $img="<p><img src=\"$me/a.png?s=$t2\" /></p>";
}
echo <<<END_HTML
<html>
<body>
$img
<form action="$me" method="get">
<input type="text" name="s" size="40" value="$t1" />
<input type="submit" value="Go" />
</form>
END_HTML;
if(!isset($_GET['s'])) exit();
?>

1
якщо ви використовуєте, imagecreatetruecolorви можете скинути перший розподіл і використовувати ім'я функції безпосередньо на другому, для -11. []замість array(). і foreach($a as$v)працює також
Ейнасіо

3

GTB

Цей код є другим найскладнішим кодом, який я коли-небудь писав для калькулятора. Немає твердо кодованих піксельних значень, він фактично малює текст на графіку і циклічно підраховує кожен піксель.

0→I`_%I<l?_T;1,1,s;_,I,1
C;pT;{0,1,2,3,4,5},{0,1,2}→L1(I
0→I%I<l?_T;1,C;L1(I)>L1,I

Вхідні дані

,O.i

Вихідні дані

.,iO

Якщо це працює, це найкраща відповідь поки що. Що б не було GTB?
нахил

@slater Чому ти не натиснеш на посилання і не дізнаємось?
Timtech

Дякуємо, що вказали, що назва вашого посту - це посилання.
схил

2
Домен для отримання програмного забезпечення, необхідного для розшифрування компілятора, мертвий . Тут також мертві . Я переклав код вручну для задоволення перевірити його, але ви, здається, відкрили 10 паронів і закрили лише один, тож я не знаю, як це вирішити. Компілятор в моїй голові каже: "Помилка ::
невідповідний

1
@JonathanVanMatre Не хвилюйся; TI-84 автоматично закриває їх для вас.
Timtech

3

Ява - 468 450 444

public static void main(String[]a){class c implements Comparable<c>{char d;c(char e){d=e;}public int compareTo(c o){return e(d)>e(o.d)?1:-1;}int e(char f){int a=0,x,y;BufferedImage img=new BufferedImage(99,99,1);img.getGraphics().drawString(""+f,9,80);for(y=0;y<99;y++)for(x=0;x<99;x++)a+=img.getRGB(x,y);return a;}}c[]s=new c[a[0].length()];int i=0;for(char d:a[0].toCharArray())s[i++]=new c(d);Arrays.sort(s);for(c d:s)System.out.print(d.d);}

@+.0abcdefghijklmnopqrstuvwxyz -> .irl+jcvtfxyzsuonkheaqpdb0wgm@

Безумовно:

    public static void main(String[] a) {
    a = new String[]{"@+.0abcdefghijklmnopqrstuvwxyz"};
    class c implements Comparable<c> {
        char    d;

        c(char e) {
            d = e;
        }

        @Override
        public int compareTo(c o) {
            return e(d) > e(o.d)? 1 : -1;
        }

        int e(char f) {
            int a = 0, x, y;
            BufferedImage img = new BufferedImage(99, 99, 1);
            img.getGraphics().drawString("" + f, 9, 80);
            for (y = 0; y < 99; y++)
                for (x = 0; x < 99; x++)
                    a += img.getRGB(x, y);
            return a;
        }
    }
    c[] s = new c[a[0].length()];
    int i = 0;
    for (char d : a[0].toCharArray())
        s[i++] = new c(d);
    Arrays.sort(s);
    for (c d : s)
        System.out.print(d.d);
}

Порада: уникайте державних чи приватних модифікаторів, наскільки це можливо; що зберігає зайві байти
masterX244

забув про все це
Марк Єронімус

@MarkJeronimus Це був спосіб, коли я збирався його відірвати, але я хотів спробувати використовувати FontRenderingContext.
Чарівний восьминога Урна

3

Постскрипт, 381

Ось щось зовсім інше, просто для розваги. Оскільки більшість шрифтів все-таки є векторними, "підрахунок пікселів" є дивним, чи не так. Обчислити площу форми гліфів, будучи правильним способом, не так просто. Альтернативою може бути сканування прямокутника та підрахунок "хітів", коли точка знаходиться у формі гліфів, а у "Постскрипта" є оператори для цього виду перевірок. Хоча правда, сканування та тестування на внутрішність - просто дивний спосіб підрахунку пікселів.

(%stdin)(r)file token pop/Courier 99 selectfont[1 index length{0}repeat]0 1 99{0 1 99{0 1 5 index length 1 sub{newpath 9 19 moveto 3 copy 7 index exch 1 getinterval false charpath infill{3 index exch 2 copy get 1 add put}{pop}ifelse}for pop}for pop}for 0 1 99 dup mul{0 1 3 index length 1 sub{dup 3 index exch get 2 index eq{3 index exch 1 getinterval print}{pop}ifelse}for pop}for

.

(%stdin) (r) file token pop
/Courier 99 selectfont
%/DejaVuSansMono 99 selectfont
%/UbuntuMono-Regular 99 selectfont
[ 1 index length {0} repeat ]   % str []
0 1 99 {
    0 1 99 {
        0 1 5 index length 1 sub {
            newpath 
            9 19 moveto
            3 copy              % str [] n m i n m i
            7 index exch        % str [] n m i n m str i
            1 getinterval       % str [] n m i n m s
            false charpath      % str [] n m i n m
            infill              % str [] n m i bool
            {3 index exch 2 copy get 1 add put} {pop} ifelse
        } for
        pop
    } for
    pop
} for
% un-comment next line to print number of 'hits' for each glyph
%
% dup {=} forall
%
% next is 'lazy sort'
0 1 99 dup mul {                % str [] i
    0 1 3 index length 1 sub {  % str [] i j
        dup 3 index exch        % str [] i j [] j
        get 2 index eq          % str [] i j bool
        {3 index exch 1 getinterval print} {pop} ifelse
    } for
    pop
} for
()=

Ось результати для трьох різних шрифтів (вибір яких можна коментувати вище):

$ echo '(.-?@AByz01)' | gs -q -dBATCH d.ps
.-?1z0yA@B
$ echo '(.-?@AByz01)' | gs -q -dBATCH d.ps
.-?z1yA0B@
$ echo '(.-?@AByz01)' | gs -q -dBATCH d.ps
.-?1zyA0B@

Підрахунок пікселів ... підрахунок пікселів перетину ... помідор .... tomahto ....
Джонатан Ван Матре

2

Perl (з GD) (159)

use GD;sub i{$i=new GD'Image 5,8;$B=colorExact$i 9,9,9;colorExact$i 0,0,0;char$i gdTinyFont,0,0,@_,1;$_=unpack"B*",wbmp$i 0;y/0//c}print+sort{i($a)-i($b)}@ARGV

використання:

> perl dark.pl 1 2 3 @ # . , : ~ $ M i I s S
.,~:i13Is2S$M@#

правка: скорочено до 159 символів


2

Ява, 584

Нічого ... Це була не гарна мова для цього.

import java.awt.geom.*;import java.util.*;class F{static void n(final String f,List<Character> s){Collections.sort(s,new Comparator<Character>(){public int compare(Character a,Character b){return d(f,""+a) - d(f,""+b);}});}static int d(String f,String s){int i=0;PathIterator p=new java.awt.Font(f,0,12).createGlyphVector(((java.awt.Graphics2D)new java.awt.image.BufferedImage(8,8,2).getGraphics()).getFontRenderContext(),s).getGlyphOutline(0).getPathIterator(AffineTransform.getRotateInstance(0.0, 0.0));while(!p.isDone()){i+=p.currentSegment(new double[99])/2;p.next();}return i;}}

Використання:

import java.awt.geom.*;
import java.util.*;
public class F {
    public static void main(String[]args){
        List<Character> s = new ArrayList<Character>(0);
        s.add('@');
        s.add('+');
        s.add('.');
        s.add('0');
        n("Calibri", s);
        System.out.println(s);
    }
    static void n(final String f,List<Character> s){
        Collections.sort(s,new Comparator<Character>(){
            public int compare(Character a,Character b){
                return d(f,""+a) - d(f,""+b);
            }
        });
    }

    static int d(String f,String s){
        int i=0;
        PathIterator p=new java.awt.Font(f,0,12).createGlyphVector(((java.awt.Graphics2D)new java.awt.image.BufferedImage(8,8,2).getGraphics()).getFontRenderContext(),s).getGlyphOutline(0).getPathIterator(AffineTransform.getRotateInstance(0.0, 0.0));
        while(!p.isDone()){
            i+=p.currentSegment(new double[99])/2;
            p.next();
        }
        return i;
    }
}

Ця настройка призводить до:

[., +, 0, @]

Єдиний рядок, який потребує пояснення:

PathIterator p=new java.awt.Font(f,0,12).createGlyphVector(((java.awt.Graphics2D)new java.awt.image.BufferedImage(8,8,2).getGraphics()).getFontRenderContext(),s).getGlyphOutline(0).getPathIterator(AffineTransform.getRotateInstance(0.0, 0.0));
  • Ініціалізуйте об'єкт шрифту 12pt з переданим шрифтом.
  • Створіть новий об'єкт BufferedImage, щоб створити об’єкт Graphics2D, пов’язаний із GraphicsContext.
  • Отримайте контекст візуалізації шрифту 2D графічного контексту для рядка s.
  • Отримайте перший рядок (лише гліф) у рядку.
  • Отримайте ітератор шляху (список точок).

Потім цей фінальний твір об'єднує його ...

while(!p.isDone()){
    i+=p.currentSegment(new double[99])/2;
    p.next();
}

Ітерацією всіх балів та підрахунком підрахунку балів. Ця інформація про щільність передається назад до компаратора і використовується для сортування.


1

R, 195 символів

A=strsplit(scan(,""),"")[[1]];cat(A[order(sapply(A,function(x){png('a',a='none',fa='monospace');frame();text(0,0,x);dev.off();sum(apply(png::readPNG('a'),c(1,2),function(x)any(x!=1)))}))],sep="")

Відступ із коментарями:

A=strsplit(scan(,""),"")[[1]] #Take characters as strings and split into single chars
cat(A[order(sapply(A,function(x){ #Apply the following function to each char and order accordingly
                 png('a',a='none',fa='monospace'); #Open empty png without antialiasing and with monospace font
                 frame(); #create empty plot
                 text(0,0,x); #add the char as text to the plot
                 dev.off(); #close png device
                 sum(apply(png::readPNG('a'), #read it back as rbga 3d matrix
                           c(1,2), #check every layer (R, G, B, A)
                           function(x)any(x!=1))) #if any are not 1, send TRUE
                 }))], #Sum all TRUEs
    sep="") #Prints to output

Приклад:

> A=strsplit(scan(,""),"")[[1]];cat(A[order(sapply(A,function(x){png('a',a='none',fa='monospace');frame();text(0,0,x);dev.off();sum(apply(png::readPNG('a'),c(1,2),function(x)any(x!=1)))}))],sep="")
1: @+.0
2: 
Read 1 item
.+0@
> A=strsplit(scan(,""),"")[[1]];cat(A[order(sapply(A,function(x){png('a',a='none',fa='monospace');frame();text(0,0,x);dev.off();sum(apply(png::readPNG('a'),c(1,2),function(x)any(x!=1)))}))],sep="")
1: 1234567890
2: 
Read 1 item
1723450689

Подача шрифтів у R-графіках залежать від платформи, я не можу гарантувати, що він працює на ПК, але він працює на Mac (OS X 10.7.5, R 2.14.2).


1

SmileBASIC, 179 176 173 байт

INPUT S$DIM Q$[0],A[0],Z[0]WHILE""<S$C$=POP(S$)GCLS
PUSH Q$,C$
GPUTCHR.,0,C$
GSAVE.,0,8,8,A,0S=0FOR I=0TO 63S=S+A[I]NEXT
PUSH Z,S
WEND
RSORT Z,Q$
WHILE LEN(Q$)?POP(Q$);
WEND

Використовується завантажений шрифт. Шрифти можна завантажувати LOAD"GRPF:filename".

Більш читабельний код:

INPUT STRING$
DIM CHARS$[0],PIXELS[0],SIZES[0]
WHILE STRING$>""
 CHAR$=POP(STRING$)
 PUSH CHARS$,CHAR$
 GCLS
 GPUTCHR 0,0,CHAR$
 GSAVE 0,0,8,8,PIXELS
 SIZE=0
 FOR I=0 TO 63
  INC SIZE,PIXELS[I]
 NEXT
 PUSH SIZES,SIZE
WEND
RSORT SIZES,CHARS$
WHILE LEN(CHARS$)
 PRINT POP(CHARS$);
WEND

0

PHP - 485

Демонстрація:

$ php pcg-23362.php "@+.0"
.+0@

Код:

<?php $f='x.ttf';$d=array();foreach(str_split($argv[1]) as$_){$B=imagettfbbox(50,0,$f,$_);$w=abs($B[4]-$B[0]);$h=abs($B[5]-$B[1]);$im=imagecreate($w,$h);imagecolorallocate($im,255,255,255);imagettftext($im,50,0,0,$h-$B[1],imagecolorallocate($im,0,0,0),$f,$_);$b=$w*$h;for($x=0;$x<$w;$x++)for($y=0;$y<$h;$y++){$z=imagecolorsforindex($im,imagecolorat($im,$x,$y));$color=$z['red']*$z['green']*$z['blue'];$b-=$color/0x1000000;}$d[$_]=$b / ($w * $h);}asort($d);echo implode(array_keys($d));

Гей, надішліть мені копію X.TTF ... найкоротший у мене шрифт - OCR A. ;-D
Джонатан Ван Матре

0

Python + freetype-py: 147

import sys,freetype as F;f=F.Face('m.ttf');f.set_char_size(99);print(sorted([(f.load_char(c)or sum(f.glyph.bitmap.buffer),c)for c in raw_input()]))
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.