按黑暗排序字符


38

您的程序必须将一行字符作为输入,如下所示:

@+.0

并输出按其暗淡程度排序的字符,如下所示:

.+0@

要求:

  • 您必须使用等宽字体进行暗度检测。

  • 您必须找出每个字符占用多少像素。实际上,您必须绘制字符并计算像素,即您不能仅对像素数量进行硬编码。

    • 作为更具体的规则:如果您切换了字体,您的程序应该仍然可以运行。此外,您的程序应该能够通过简单地更改代码中的变量,值或字符串来切换字体。
  • 如果使用抗锯齿,则必须将像素计数为全黑像素的百分比。例如,一个rgb(32, 32, 32)像素将算作整个像素的1/8。如果您的角色没有抗锯齿,请忽略此规则。

  • 计算像素后,必须按字符数量对字符进行排序,然后按顺序输出它们。

  • 这是,因此以字节为单位的最短代码将获胜。


7
奇怪的是,这也适用于RPG.se!
corsiKa 2014年

1
什么,在暗度计算中无法校正显示伽玛?
Ilmari Karonen 2014年

6
我们可以使用白色字体吗?如果是这样,我想我已经把这个包裹了。
保罗

Answers:


22

数学,112 110 108个字节

这仍然有可能进一步打高尔夫球。假设字符串在变量s中。

现在,使用正确的语法按一个列表对另一个列表进行排序。
幸运的测试用例->“哦,行得通”-> Facepalm
感谢您敏锐的目光,David Carraher。

更新:用Menlo替换了OCR A,因为我意识到在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];“ Courier”的输出

在此处输入图片说明

输出相同,但带有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 2014年

是否为默认系列,规格要求“您的程序应该能够通过简单地更改变量来切换字体”。由于使用了抗锯齿值,因此可能会出现某些看起来错误的类型,但是我将再次查看整个范围,看看是否有任何错误。
Jonathan Van Matre 2014年

1
多么棒的语言!前几天刚发现Wolfram的新编程语言成果,对此很期待。
the0ther

1
通过将Characters []更改为Characters @,将Reverse []更改为Reverse @,可以节省两个字节。
Michael Stern 2014年

2
我不想发布类似的答案,但是我尝试了一下,结果变得更短StringJoin@SortBy[Characters@"@+.0",ImageData@Binarize@Rasterize@Style[#,FontFamily->"Monospace"]~Total~2&]
激起2014年

25

Bash + ImageMagick:164147148 字符

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 2014年

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会插入的空格),但这可能不值得,因为此答案无论如何都不会赢。

Q按黑暗对字符进行基本排序


再加上一个有趣的做事!
Jonathan Van Matre 2014年

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

也许可以打更多的高尔夫球。

我是该网站的新手,所以不确定如何正常读取Java答案的输入。我假设输入包含在名为的变量中s。如果这样不行,我将更新答案和字符计数。

JSFiddle的更新版本。

JSFiddle的第一个版本


我真的很喜欢,但是这里有很多可能的改进。变量cs是不必要的(a=document.createElement('canvas').getContext('2d')y+=a.getImageData(0,0,30,30).data[i]),不需要附加元素,y可以将ii=y=0)的零初始化与()组合,将()的后增量iyfor(...;y+=...[i++]);)的添加相结合,以及字体摩纳哥是等距的,并且名称比Courier短。
Fors 2014年

谢谢!我还不是一个经验丰富的高尔夫球手,所以您的意见很有帮助。我现在将它们合并到代码中。
蜡翼

这里的Javascript答案通常通过以下方式读取输入prompt():但这也很好。
Kartik

您可以删除y=i=0;并更改a.fillText(x,0,20)a.fillText(x,y=i=0,20)
牙刷2014年

谢谢,以及添加!两个字符就是两个字符!
蜡翼2014年

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

此代码使用PHP内置的GD字体。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 2014年

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 2014年

@slater为什么不单击链接并查找?
Timtech

感谢您指出您的帖子标题确实是链接。
slater 2014年

2
获取用于解密编译器所需软件的域已失效这里也死了 我手动翻译了代码,以进行测试,但您似乎打开了10个parens,但只关闭了一个parins,所以我不确定如何解决。我脑海中的编译器说:“ Error ::
unmatched

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 2014年

一切都忘了
Mark Jeronimus 2014年

@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对象以创建链接到GraphicsContext的Graphics2D对象。
  • 获取字符串s的2D图形上下文的字体呈现上下文。
  • 获取字符串中的第一个字形(仅字形)。
  • 获取路径迭代器(点列表)。

然后这最后一块将其组合在一起...

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图形中字体的字体依赖于平台,我不能保证它可以在PC上运行,但可以在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的副本...我拥有的最短字体是
OCRA。;-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()]))
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.