Ordenar personajes por oscuridad

38

Su programa debe tomar como entrada una línea de caracteres, como esta:

@+.0

Y muestra los caracteres ordenados por cuán oscuros son, de esta manera:

.+0@

Requisitos:

  • Debe usar una fuente monoespaciada para la detección de oscuridad.

  • Debes averiguar cuántos píxeles ocupa cada personaje. En realidad, debe dibujar el carácter y contar píxeles, es decir, no puede simplemente codificar cantidades de píxeles.

    • Como regla más concreta: si cambiaste de fuente, tu programa aún debería funcionar. Además, su programa debería poder cambiar las fuentes simplemente cambiando una variable o valor o cadena en el código.
  • Si usa antialiasing, debe contar los píxeles como porcentajes de un píxel completamente negro. Por ejemplo, un rgb(32, 32, 32)píxel contará como 1/8 de un píxel completo. Haga caso omiso de esta regla si sus personajes no tienen antialias.

  • Después de contar los píxeles, debe ordenar los caracteres por la cantidad de píxeles y mostrarlos en orden.

  • Este es el , por lo que ganará el código más corto en bytes.

Pomo de la puerta
fuente
77
Por extraño que parezca, esto también es apropiado para RPG.se!
corsiKa
1
¿Qué, ninguna corrección para mostrar gamma en el cálculo de oscuridad?
Ilmari Karonen
66
¿Podemos usar una fuente blanca? Si es así, creo que tengo este envuelto.
Paul

Respuestas:

22

Mathematica, 112 110 108 bytes

Es probable que esto todavía se pueda jugar más. Asume que la cadena está en la variable s.

Y ahora usa una sintaxis correcta para ordenar una lista por otra lista.
Casos de prueba afortunados -> "Oh sí, eso funciona" -> Facepalm
Gracias por los ojos agudos, David Carraher.

Actualizar: Reemplacé OCR A con Menlo porque me di cuenta de que en OSX el nombre de la familia de fuentes OCR A es en realidad OCR A Std. Así que estaba ordenando una fuente predeterminada en lugar de la verdadera. Menlo también está monoespaciado con el mismo número de bytes, por lo que no hay ganancia o pérdida neta.

He puesto una exportación de CDF alojada del portátil , para que pueda ver el código en acción si lo desea. Todavía estoy descubriendo cómo agregar algo de interactividad a los CDF alojados en la web, por lo que por ahora es solo estático.

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

Salida para s = FromCharacterCode /@ Range[33, 135];con "Courier"

ingrese la descripción de la imagen aquí

Salida para lo mismo, pero con FontFamily "Monospace":

ingrese la descripción de la imagen aquí

Tenga en cuenta que los resultados finales se muestran en la fuente interna de MM, no en la fuente que se está ordenando. Por lo tanto, verá las diferencias en la fuente elegida reflejadas en el orden. Sin embargo, el enlace CDF muestra ambos para los completistas.

Código sin golf:

s = FromCharacterCode /@ Range[33, 135];
c = Characters@s;
Last /@ Sort[
    Transpose@{Total[1 - # & /@ 
        ImageData@Rasterize@Style[#, FontFamily -> "Menlo"], 3] & /@ c, c}]
Jonathan Van Matre
fuente
1
Examine esta entrada:"" <> (FromCharacterCode /@ Range[33, 135])
DavidC
Familia predeterminada o no, las especificaciones requeridas "su programa debería poder cambiar las fuentes simplemente cambiando una variable". Debido a los valores de suavizado, es posible obtener algunos tipos que parecen incorrectos, pero volveré a examinar el rango completo y veré si algo está mal.
Jonathan Van Matre
1
¡Qué lenguaje tan fabuloso! Acabo de enterarme del nuevo esfuerzo de lenguaje de programación de Wolfram el otro día, esperando eso.
the0ther
1
Puede guardar dos bytes cambiando Caracteres [] a Caracteres @ y Reverse [] a Reverse @.
Michael Stern
2
No quiero publicar una respuesta similar, pero lo intenté y fue más corto StringJoin@SortBy[Characters@"@+.0",ImageData@Binarize@Rasterize@Style[#,FontFamily->"Monospace"]~Total~2&]
swish
25

Bash + ImageMagick: 164 147 148 caracteres

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[@]}"

Ejecución de muestra:

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

Los separadores se insertan entre los grupos de gris. Los caracteres con un nivel de gris idéntico no están separados:

bash-4.1$ echo -n 'abcdefghijklmnopqrstuvwxyz' | bash graysort.sh
i cl jortz esv ax u df bgnpq y hk w m
hombre trabajando
fuente
+1 para ordenar usando índices de matriz bash en lugar desort
Digital Trauma
9

QBasic, 259 bytes

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

Lo hice por diversión, por lo que técnicamente no cumple con las reglas de una manera. No toma una lista de caracteres, sino que imprime todos los caracteres de 32-255 y los usa en su lugar. Si realmente desea ver una versión que cumpla con esta regla, dígame.

También falla otro tecnicismo: "Además, su programa debería ser capaz de cambiar las fuentes simplemente cambiando una variable o valor o cadena en el código". No hay una manera fácil de hacer esto desde QBasic. Sin embargo, el programa, por supuesto, funcionará bien con cualquier página de códigos que elija.

Por último, podría eliminar algunos caracteres (en su mayoría espacios en blanco que el IDE QBasic inserta útilmente), pero probablemente no valga la pena ya que esta respuesta no tiene posibilidades de ganar de todos modos.

Q Ordenar personajes básicos por oscuridad

nitro2k01
fuente
¡Más uno por hacerlo por diversión!
Jonathan Van Matre
8

Javascript + Canvas y DOM del navegador ( 280 237 235 bytes)

Versión actualizada con sugerencias de Fors y cepillo de dientes en los comentarios:

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(''))

Versión más legible:

// 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(''))

Tal vez se pueda jugar más al golf.

Soy nuevo en este sitio, así que no estoy seguro de cómo se lee normalmente la entrada para las respuestas de Javascript. Supongo que la entrada está contenida en una variable llamadas . Si esto no está bien, actualizaré la respuesta y el recuento de caracteres.

JSFiddle de versión actualizada.

JS Violín de la primera versión .

Waxwing
fuente
Realmente me gusta, sin embargo, hay muchas posibles mejoras aquí. Las variables cy sson innecesarias ( a=document.createElement('canvas').getContext('2d')y y+=a.getImageData(0,0,30,30).data[i]), el elemento no necesita ser agregado, la inicialización cero de yse puede combinar con la de i( i=y=0), el post-incremento de ise puede combinar con la suma de y( for(...;y+=...[i++]);) y el tipo de letra Mónaco es monoespaciado y tiene un nombre más corto que Courier.
Fors
¡Gracias! Todavía no soy un golfista experimentado, por lo que sus comentarios ayudan mucho. Los he incorporado al código ahora.
Waxwing
Las respuestas de Javascript aquí normalmente leen la entrada prompt(); Pero esto también está bien.
Kartik
Puede eliminar y=i=0;y cambiar a.fillText(x,0,20)a a.fillText(x,y=i=0,20).
Cepillo de dientes
Gracias, agregó que también! ¡Dos personajes son dos personajes!
Waxwing
3

PHP, 298 caracteres

He agregado algunos saltos de línea para que pueda verlo en toda su horrible:

<?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);

Este código usa las fuentes GD que vienen con PHP. El segundo argumento de imagechar()selecciona la fuente (los números del 1 al 5 son válidos).

Ejemplo:

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

Si inserta lo siguiente en la parte superior del código que se muestra arriba, podrá proporcionar la lista de caracteres en su navegador web.

<?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();
?>
ossifrage aprensivo
fuente
1
si lo usa imagecreatetruecolor, puede soltar la primera asignación y usar el nombre de la función directamente en la segunda, para -11. []en lugar de array(). y foreach($a as$v)funciona bien
Einacio
3

GTB

Este tiene el código para ser el segundo código más difícil que he escrito para una calculadora. Sin valores de píxel codificados, en realidad dibuja el texto en un gráfico y realiza un bucle para contar cada píxel.

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

Entrada

,O.i

Salida

.,iO
Timtech
fuente
Si esto funciona, es la mejor respuesta hasta ahora. ¿Qué es GTB?
Slater
@Slater ¿Por qué no hace clic en el enlace y lo descubre?
Timtech
Gracias por señalar que el título de tu publicación es de hecho un enlace.
Slater
2
El dominio para obtener el software necesario para descifrar su compilador está muerto . Muerto aquí también. Traduje el código a mano por el gusto de probarlo, pero parece que has abierto 10 parens y cerrado solo uno, así que no estoy seguro de cómo resolverlo. El compilador en mi cabeza dice: "Error :: identificador sin igual" :)
Jonathan Van Matre
1
@JonathanVanMatre No te preocupes; TI-84 los cierra automáticamente por usted.
Timtech
3

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

Sin golf:

    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);
}
Mark Jeronimus
fuente
Consejo: evite los modificadores públicos o privados en la medida de lo posible; que ahorra bytes innecesarios
masterX244
olvidé todo eso
Mark Jeronimus
@ MarkJeronimus esta era la forma en que lo iba a abordar, pero quería intentar usar FontRenderingContext.
Urna de pulpo mágico
3

Postdata, 381

Aquí hay algo completamente diferente, solo por diversión. Como la mayoría de las fuentes son vectores de todos modos, 'contar píxeles' es un poco extraño, ¿no? Calcular el área de forma de glifo, aunque es la forma correcta, no es tan fácil. Una alternativa puede ser escanear un rectángulo y contar 'golpes' cuando un punto está dentro de una forma de glifo, y Postscript tiene operadores para este tipo de comprobaciones. Sin embargo, es cierto, el escaneo y las pruebas de interioridad son solo una forma extraña de contar píxeles.

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

Y aquí están los resultados para 3 fuentes diferentes (la selección de las cuales puede estar sin comentarios, arriba):

$ 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@
usuario2846289
fuente
Contando píxeles ... contando intersecciones de píxeles ... tomate .... tomahto ....
Jonathan Van Matre
2

Perl (con 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

uso:

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

editar: acortado a 159 caracteres

perl chino goth
fuente
2

Java, 584

Wow ... Este no era un buen lenguaje para hacer esto.

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;}}

Uso:

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;
    }
}

Esta configuración da como resultado:

[., +, 0, @]

La única línea aquí que necesita explicación:

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));
  • Inicialice el objeto de fuente 12pt con la fuente pasada.
  • Cree un nuevo objeto BufferedImage para crear un objeto Graphics2D vinculado a un GraphicsContext.
  • Obtenga el contexto de representación de fuente del contexto de gráficos 2D para la cadena s.
  • Obtenga el primer glifo (solo glifo) en la cadena.
  • Obtenga el iterador de ruta (lista de puntos).

Entonces esta pieza final lo une ...

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

Al iterar a través de todos los puntos y sumar el recuento de puntos. Esta información de densidad se devuelve al comparador y se utiliza para ordenar.

Urna de pulpo mágico
fuente
1

R, 195 caracteres

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="")

Sangrado con comentarios:

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

Ejemplo:

> 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

La gestión de las fuentes en los gráficos R depende de la plataforma, no puedo garantizar que funcione en PC, pero lo hace en una Mac (OS X 10.7.5, R 2.14.2).

plannapus
fuente
1

SmileBASIC, 179 176 173 bytes

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

Utiliza la fuente cargada actualmente. Las fuentes se pueden cargar conLOAD"GRPF:filename" .

Código más legible:

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
12Me21
fuente
0

PHP - 485

Manifestación:

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

Código:

<?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));
TimWolla
fuente
Hola, envíeme una copia de X.TTF ... la fuente más corta que tengo es OCR A. ;-D
Jonathan Van Matre
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()]))
Mathieu Rodic
fuente