Addition de graphiques colorés

9

Dans certains cas, souvent en physique, vous devez additionner des graphiques. Votre défi consiste à écrire, dans la langue de votre choix, un programme ou une fonction qui prend plusieurs graphiques en images, calcule toutes les sommes possibles et affiche le résultat.

Graphiques

Les graphiques sont des images qui contiennent un rgb(255, 255, 255)arrière-plan blanc ( ) avec un pixel non blanc dans chaque colonne. Exemples:

exemple de graphique exemple de graphique exemple de graphique

Les valeurs du script sont représentées par les positions Y des pixels colorés. La valeur à une certaine coordonnée X est égale à la position Y du pixel coloré le plus haut dans cette colonne, avec des coordonnées commençant à 0 en bas à gauche. Il peut y avoir ou non des pixels colorés supplémentaires en dessous de ces pixels pour des raisons esthétiques.

Tâche

Votre tâche consiste à écrire, dans la langue de votre choix, un programme ou une fonction qui prend plusieurs graphiques en images, calcule toutes les 2^n - 1sommes possibles et génère le résultat.

Une somme de graphiques est un graphique où la valeur de chaque colonne est égale à la somme des valeurs de la colonne correspondante dans chacun des graphiques d'entrée.

Les graphiques seront disponibles en plusieurs couleurs. L'image résultante doit contenir toutes les sommes possibles des graphiques comme les autres graphiques, y compris les graphiques d'origine mais à l'exclusion de la somme nulle.

La couleur de chaque somme est déterminée par la moyenne des couleurs des graphiques inclus, par exemple, des graphiques de couleurs rgb(255, 0, 255)et rgb(0, 255, 255)produirait un graphique de rgb(128, 128, 255)(peut également être arrondi vers le bas).

L'image résultante doit être aussi haute que nécessaire pour s'adapter à tous les graphiques. Cela signifie que vous devrez peut-être produire une image plus grande que n'importe laquelle des entrées.

L'ordre dans lequel les graphiques résultants sont dessinés sur l'image résultante n'a pas d'importance, c'est-à-dire que si les graphiques résultants se chevauchent, vous pouvez choisir celui qui est en haut, mais ce doit être l'un des graphiques, pas une combinaison de leurs couleurs.

Vous pouvez supposer que les images d'entrée sont de largeur égale, que toutes les colonnes des images ont au moins un pixel non blanc et que les hauteurs des images (y compris la sortie) sont inférieures à 4096 pixels.

Exemple

Entrée A:

exemple graphique un

Entrée B:

exemple de graphique b

Exemple de sortie:

exemple de somme de graphique

(Au cas où quelqu'un serait intéressé, j'ai copié-collé les données pour celles-ci à partir des graphiques boursiers d'entreprises aléatoires. C'était la première façon que j'ai trouvée pour obtenir des données réalistes en CSV.)

Règles

  • Vous pouvez choisir n'importe quel format de fichier d'entrée d'image bitmap.
  • Vous pouvez choisir n'importe quel format de fichier de sortie d'image bitmap, qui ne doit pas nécessairement correspondre à l'entrée.
  • Vous pouvez utiliser des bibliothèques de traitement d'images, mais toutes les fonctions permettant d'effectuer directement cette tâche sont interdites.
  • Des échappatoires standard s'appliquent.
  • C'est le , donc le code le plus court en octets gagne.

Script de générateur de graphes

Voici un script Python 2 qui génère des graphiques. L'entrée est donnée en lignes, avec les trois premières lignes comme couleur RVB et les autres comme données, terminées par EOF.

import PIL.Image as image
import sys

if len(sys.argv) < 2:
    sys.stderr.write("Usage: graphgen.py <outfile> [infile]")
    exit(1)
outfile = sys.argv[1]
if len(sys.argv) > 2:
    try:
        stream = open(sys.argv[2], "r")
        data = stream.read()
        stream.close()
    except IOError as err:
        if err.errno == 2:
            sys.stderr.write("File \"{0}\" not found".format(sys.argv[2]))
        else:
            sys.stderr.write("IO error {0}: {1}".format(err.errno, err.strerror))
        exit(1)
else:
    data = sys.stdin.read()

try:
    items = map(int, data.strip().split("\n"))
    red, green, blue = items[:3]
    items = items[3:]
    highest = max(items)
except (ValueError, TypeError, IndexError):
    sys.stderr.write("Invalid value(s) in input")

img = image.new("RGB", (len(items), highest + 1), (255, 255, 255))

prev = items[0]
img.putpixel((0, highest - items[0]), (red, green, blue))
for x, item in enumerate(items[1:]):
    img.putpixel((x + 1, highest - item), (red, green, blue))
    if item < prev:
        for i in range(item + 1, prev):
            img.putpixel((x, highest - i), (red, green, blue))
    else:
        for i in range(prev + 1, item):
            img.putpixel((x + 1, highest - i), (red, green, blue))
    prev = item

img.save(outfile, "png")
PurkkaKoodari
la source
@ MartinBüttner Je fais actuellement un pour deux graphiques. Je le fais à la main (aucune référence implicite pour le moment), donc je ne sais pas si j'ai la patience pour 3. De plus, les trois que j'ai donnés ne peuvent pas être additionnés car ils sont de largeurs différentes.
PurkkaKoodari
Donc, s'il y a ndes graphiques d'entrée, il y aura des 2^n - 1lignes dans l'image de sortie?
Peter Taylor
@PeterTaylor Oui.
PurkkaKoodari
Je suppose que la sortie n'a pas besoin de contenir de lignes verticales? Seul le pixel le plus haut de chaque colonne?
Martin Ender
@ MartinBüttner C'est exact, car ces données peuvent toujours être analysées sous forme de graphique comme défini dans la première section.
PurkkaKoodari

Réponses:

3

MATLAB, 405

Appelez via: f('http://i.stack.imgur.com/ffCzR.png','http://i.stack.imgur.com/zHldg.png')

function f(varargin)
for k=1:nargin
i=im2double(imread(varargin{k}))
V(k,:)=size(i,1)-cellfun(@(V)find(any(V~=1,3),1),num2cell(i,[1,3]))
C(k,:)=i(find(any(i(:,1,:)~=1,3),1),1,:)
end
s=2^nargin-1
G=dec2bin(1:s)-'0'
C=bsxfun(@rdivide,G*C,sum(G,2))
V=G*V
m=max(V(:))
r=ones(m+1,size(V,2))
g=r
b=r
for i=1:s
M=bsxfun(@eq,(m:-1:0).',V(i,:))
r(M)=C(i,1)
g(M)=C(i,2)
b(M)=C(i,3)
end
imwrite(cat(3,r,g,b),'S.png')
knedlsepp
la source
4

Python, 422

Appel depuis la ligne de commande python plotsum im1.png im2.png im3.png

import sys
from numpy import*
from scipy import misc as m
R=m.imread
r=range
a=array
N=sys.args[1:]
L=len(N)
P=[map(argmin,R(n,1).T)for n in N]               #converts image to list of heights, counting from the top
C=a([R(N[i])[P[i][0],0,:]for i in r(L)])         #finds and stores the colour
P=a([len(R(N[i]))-a(P[i])for i in r(L)])         #flips the numbers, measures actual heights from bottom
w=len(P[0])
h=max(sum(P,0))+1                                    #compute dimensions
G=ones((h,w,3))*255                                  #and make a white grid
for i in r(1,2**L):
 z=where(a(list(bin(i)[2:].zfill(L)))=='1');y=sum(P[z],0)    #sum the graphs
 for x in r(w):G[y[x],x,:]=average(C[z],0)                   #average the colours
m.imsave('S.png',G[::-1])                            #flip image vertically and save

Exemple de sortie
entrez la description de l'image ici
Un autre exemple
entrez la description de l'image ici

C'était une opération délicate, les opérations de tableau de haut niveau et l'utilisation de tableaux comme indices aide beaucoup ici. Je ne m'attends pas à voir des solutions de moins de 1000 octets, sauf dans Mathematica et Matlab

DenDenDo
la source