Ordina i personaggi per oscurità


38

Il tuo programma deve assumere come input una riga di caratteri, in questo modo:

@+.0

E crea i personaggi ordinati per quanto sono scuri, in questo modo:

.+0@

Requisiti:

  • È necessario utilizzare un carattere a spaziatura fissa per il rilevamento dell'oscurità.

  • Devi scoprire quanti pixel occupa ogni personaggio. In realtà devi disegnare il personaggio e contare i pixel, cioè non puoi limitarti a stabilire un numero di pixel hardcode.

    • Come regola più concreta: se hai cambiato font, il tuo programma dovrebbe comunque funzionare. Inoltre, il tuo programma dovrebbe essere in grado di cambiare carattere semplicemente cambiando una variabile o un valore o una stringa nel codice.
  • Se si utilizza l'antialias, è necessario contare i pixel come percentuali di un pixel completamente nero. Ad esempio, un rgb(32, 32, 32)pixel verrà conteggiato come 1/8 di un pixel intero. Ignora questa regola se i tuoi personaggi non sono anti-alias.

  • Dopo aver contato i pixel, è necessario ordinare i caratteri in base alla quantità di pixel e riprodurli in ordine.

  • Questo è , quindi vincerà il codice più breve in byte.


7
Stranamente, questo è appropriato anche per RPG.se!
corsiKa

1
Cosa, nessuna correzione per la gamma di visualizzazione nel calcolo dell'oscurità?
Ilmari Karonen,

6
Possiamo usare un carattere bianco? Se è così, penso di averlo concluso.
Paul

Risposte:


22

Mathematica, 112 110 108 byte

Questo può probabilmente essere ulteriormente approfondito. Presuppone che la stringa sia nella variabile s.

E ora utilizza una sintassi corretta per ordinare un elenco in base a un altro elenco.
Casi di test fortunati -> "Oh sì, funziona" -> Facepalm
Grazie per gli occhi acuti, David Carraher.

Aggiornamento: Sostituito OCR A con Menlo perché mi sono reso conto che su OSX il nome della famiglia di caratteri OCR A è in realtà OCR A Std. Quindi stavo ordinando un font predefinito invece del vero affare. Menlo è anche monospaziato con lo stesso numero di byte, quindi nessun guadagno o perdita netti.

Ho creato un'esportazione CDF ospitata del notebook , quindi puoi vedere il codice in azione se lo desideri. Sto ancora scoprendo come aggiungere un po 'di interattività ai CDF ospitati sul web, quindi per ora è solo statico.

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

Uscita per s = FromCharacterCode /@ Range[33, 135];con "Corriere"

enter image description here

Output per lo stesso, ma con FontFamily "Monospace":

enter image description here

Si noti che i risultati finali sono mostrati nel carattere interno di MM, non nel carattere ordinato. Quindi, vedi le differenze nel carattere scelto riflesse nell'ordinamento. Il collegamento CDF mostra entrambi, tuttavia, per i completisti.

Codice non golfato:

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

1
Esamina questo input:"" <> (FromCharacterCode /@ Range[33, 135])
David

Famiglia di default o meno, le specifiche richieste "il tuo programma dovrebbe essere in grado di cambiare carattere semplicemente cambiando una variabile". A causa dei valori di antialiasing, è possibile ottenere alcuni tipi che sembrano sbagliati, ma darò un'altra occhiata all'intera gamma e vedrò se qualcosa non va.
Jonathan Van Matre,

1
che lingua formidabile! appena scoperto il nuovo sforzo del linguaggio di programmazione di Wolfram l'altro giorno, non vedo l'ora.
altro

1
È possibile salvare due byte modificando Caratteri [] in Caratteri @ e Inverti [] in Inverti @.
Michael Stern,

2
Non voglio pubblicare una risposta simile, ma ho provato me stesso ed è arrivato più cortoStringJoin@SortBy[Characters@"@+.0",ImageData@Binarize@Rasterize@Style[#,FontFamily->"Monospace"]~Total~2&]
swish

25

Bash + ImageMagick: 164 147 148 caratteri

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

Esecuzione di esempio:

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

I separatori vengono inseriti tra i gruppi di grigio. I personaggi con identico livello di grigio non sono separati:

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

+1 per l'ordinamento utilizzando gli indici di matrice bash invece disort
Digital Trauma

9

QBasic, 259 byte

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

L'ho fatto per divertimento, quindi tecnicamente non è conforme alle regole in un modo. Non prende un elenco di caratteri, ma stampa invece tutti i caratteri da 32 a 255 e lo utilizza invece. Se vuoi davvero vedere una versione conforme a questa regola, per favore dimmelo.

Fallisce anche un altro aspetto tecnico: "Inoltre, il tuo programma dovrebbe essere in grado di cambiare carattere semplicemente cambiando una variabile, un valore o una stringa nel codice." Non esiste un modo semplice per farlo da QBasic. Tuttavia, il programma funzionerà naturalmente bene con qualsiasi tabella codici di tua scelta.

Infine, potrei spremere alcuni caratteri (principalmente spazi bianchi che l'IDE QBasic inserisce utile), ma probabilmente non ne vale la pena poiché questa risposta non ha alcuna possibilità di vincere comunque.

QBasic sort characters by darkness


Più uno per farlo per divertimento!
Jonathan Van Matre,

8

Javascript + Canvas e browser DOM ( 280 237 235 byte)

Versione aggiornata con suggerimenti di Fors e spazzolino nei commenti:

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

Versione più leggibile:

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

Forse si può giocare a golf di più.

Sono nuovo di questo sito, quindi non sono sicuro di come l'input viene normalmente letto per le risposte Javascript. Presumo che l'input sia contenuto in una variabile denominata s. Se ciò non va bene, aggiornerò la risposta e il conteggio dei caratteri.

JSFiddle della versione aggiornata.

JSFiddle della prima versione .


Mi piace davvero, tuttavia ci sono molti possibili miglioramenti qui. Le variabili ce snon sono necessarie ( a=document.createElement('canvas').getContext('2d')e y+=a.getImageData(0,0,30,30).data[i]), non è necessario aggiungere l'elemento, l'inizializzazione zero di ypuò essere combinata con quella di i( i=y=0), il post-incremento di ipuò essere combinato con l'aggiunta di y( for(...;y+=...[i++]);) e il carattere tipografico Monaco è mono-spaziato e ha un nome più breve di Courier.
Fors

Grazie! Non sono ancora un golfista esperto, quindi i tuoi commenti aiutano molto. Li ho incorporati nel codice ora.
waxwing

Le risposte Javascript qui normalmente leggono input attraverso prompt(); ma anche questo va bene.
Kartik

È possibile rimuovere y=i=0;e modificare a.fillText(x,0,20)in a.fillText(x,y=i=0,20).
Spazzolino da denti

Grazie, aggiunto anche quello! Due personaggi sono due personaggi!
ceretta,

3

PHP, 298 caratteri

Ho aggiunto alcune interruzioni di riga in modo da poterlo vedere in tutta la sua orrore:

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

Questo codice utilizza i caratteri GD integrati in PHP. Il secondo argomento di imagechar()seleziona il carattere (i numeri da 1 a 5 sono validi).

Esempio:

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

Se inserisci quanto segue sopra il codice mostrato sopra, sarai in grado di fornire l'elenco dei caratteri nel tuo browser 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();
?>

1
se si utilizza imagecreatetruecolorè possibile eliminare la prima allocazione e utilizzare il nome della funzione direttamente sulla seconda, per -11. []invece di array(). e foreach($a as$v)funziona anche
Einacio

3

GTB

Questo ha il codice per essere il secondo codice più difficile che io abbia mai scritto per una calcolatrice. Nessun valore di pixel hardcoded, in realtà disegna il testo su un grafico e scorre per contare ogni pixel.

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

Ingresso

,O.i

Produzione

.,iO

Se funziona, è la risposta migliore finora. Qual è la GTB?
slater

@slater Perché non fai clic sul link e lo scopri?
Timtech

Grazie per aver sottolineato che il titolo del tuo post è davvero un link.
slater

2
Il dominio per ottenere il software necessario per decrittografare il compilatore è morto . Morto anche qui . Ho tradotto il codice a mano per divertirmi a provarlo, ma sembra che tu abbia aperto 10 parentesi e ne abbia chiuso solo uno, quindi non sono sicuro di come risolverlo. Il compilatore nella mia testa dice: "Errore :: identificatore senza pari" :)
Jonathan Van Matre

1
@JonathanVanMatre Non preoccuparti; TI-84 li chiude automaticamente per te.
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@

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

Suggerimento: evitare per quanto possibile modificatori pubblici o privati; che salva byte non necessari
masterX244

dimenticato tutto questo
Mark Jeronimus

@MarkJeronimus questo era il modo in cui lo avrei risolto, ma volevo provare a usare FontRenderingContext.
Magic Octopus Urn

3

Postscript, 381

Ecco qualcosa di completamente diverso, solo per divertimento. Dato che la maggior parte dei caratteri è comunque vettoriale, "contare i pixel" è un po 'strano, no? Calcolare l'area della forma del glifo, pur essendo il modo corretto, non è così facile. Un'alternativa può essere la scansione di un rettangolo e il conteggio di "hit" quando un punto si trova all'interno di una forma di glifo e Postscript ha operatori per questo tipo di controlli. Tuttavia, il vero test di scansione e di insideness è solo uno strano modo di contare i pixel.

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

E qui ci sono risultati per 3 diversi caratteri (la cui selezione può essere non commentata, sopra):

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

Conteggio dei pixel ... conteggio delle intersezioni di pixel ... pomodoro .... 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

utilizzo:

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

modifica: abbreviato a 159 caratteri


2

Java, 584

Wow ... Questo non era un buon linguaggio per farlo.

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

Questa configurazione comporta:

[., +, 0, @]

L'unica riga qui che necessita di spiegazioni:

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));
  • Inizializza l'oggetto font 12pt con il font passato.
  • Crea un nuovo oggetto BufferedImage per creare un oggetto Graphics2D collegato a GraphicsContext.
  • Ottieni il contesto di rendering dei caratteri del contesto grafico 2D per la stringa s.
  • Ottieni il primo glifo (solo glifo) nella stringa.
  • Ottieni l'iteratore del percorso (elenco di punti).

Quindi questo pezzo finale lo riunisce ...

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

Esaminando tutti i punti e sommando il conteggio dei punti. Queste informazioni sulla densità vengono restituite al comparatore e utilizzate per l'ordinamento.


1

R, 195 caratteri

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

Rientrato con commenti:

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

Esempio:

> 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 gestazione dei caratteri nei grafici R dipende dalla piattaforma, non posso garantire che funzioni su PC, ma su un Mac (OS X 10.7.5, R 2.14.2).


1

SmileBASIC, 179 176 173 byte

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

Utilizza il font attualmente caricato. I caratteri possono essere caricati con LOAD"GRPF:filename".

Codice più leggibile:

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

demo:

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

Codice:

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

Ehi, mandami una copia di X.TTF ... il carattere più corto che ho è 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()]))
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.