Сортировка персонажей по темноте


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. Поэтому я сортировал шрифт по умолчанию вместо реальной сделки. Menlo также моноширинный с тем же количеством байтов, так что нет чистой прибыли или потерь.

Я включил экспорт записной книжки в 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 показывает и то, и другое для полных участников.

Ungolfed код:

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&]
swish

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 + Canvas и браузер DOM ( 280 237 235 байт)

Обновленная версия с предложениями от Форса и зубной щеткой в ​​комментариях:

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++]);) и гарнитура Монако имеет одинаковое расстояние и имеет более короткое имя, чем Courier.
Форс

Благодарность! Я еще не опытный игрок в гольф, поэтому ваши комментарии очень помогают. Я включил их в код сейчас.
Wingwing

Ответы Javascript здесь обычно читают ввод через prompt(); но это тоже нормально.
Картик

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

Спасибо, добавил это тоже! Два символа - два символа!
Wingwing

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)работает так же
Einacio

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

Если это работает, это лучший ответ на данный момент. Что бы ни было ГТБ?
Слейтер

@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@

Ungolfed:

    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

Вот что-то совершенно другое, просто для удовольствия. Так как большинство шрифтов в любом случае являются векторными, «считать пиксели» немного странно, не правда ли. Вычислить площадь формы глифа, будучи правильным способом, не так просто. Альтернативой может быть сканирование прямоугольника и подсчет «попаданий», когда точка находится внутри фигуры глифа, и Postscript имеет операторы для такого рода проверок. Правда, сканирование и внутреннее тестирование - это просто странный способ подсчета пикселей.

(%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
()=

А вот результаты для 3 разных шрифтов (выбор которых можно прокомментировать выше):

$ 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@

Подсчет пикселей ... подсчет пиксельных пересечений ... помидор .... томахто ....
Джонатан Ван Матре

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.