Hungry Image Snake - Hole # 3


25

Buca n. 1

Joe il serpente ha fame.

Mangia immagini, un pixel alla volta.

Gli piacciono davvero i pixel luminosi.

La sfida

Programma Joe per consumare i pixel più luminosi che riesce a trovare, dato che può solo spostarsi verso l'alto, il basso, a sinistra o a destra.

specificazioni

  • Joe deve iniziare dal pixel in alto a sinistra dell'immagine.
  • Joe può muoversi solo orizzontalmente o verticalmente di 1 ogni mossa
  • Joe ha solo il tempo sufficiente per spostare 1/3 della quantità di pixel nell'immagine (1/3 delle mosse di pixel). Se il numero di pixel non è un multiplo di 3, arrotondare per difetto all'intero più vicino.
  • Joe può incrociare il suo cammino, anche se questo conta come 0 luminosità
  • La luminosità si basa sulla somma di r, g e b, quindi rgb (0,0,0) ha una luminosità di 0 mentre rgb (255,255,255) ha la massima luminosità.

Ingresso

Puoi inserire l'immagine come preferisci.

Produzione

  • un'immagine che mostra il risultato finale della tua foto (con pixel neri consumati).
  • La quantità di luminosità consumata (si prega di specificare quale intervallo nella risposta)

punteggio

Il tuo programma sarà valutato su:

  • La luminosità media dei pixel che Joe mangia / La luminosità media dei pixel nell'immagine *

* puoi codificarlo nel tuo programma

Il tuo punteggio totale sarà la media dei punteggi per le seguenti immagini:

Immagini di prova:

inserisci qui la descrizione dell'immagine

inserisci qui la descrizione dell'immagine

http://upload.wikimedia.org/wikipedia/en/thumb/f/f4/The_Scream.jpg/800px-The_Scream.jpg

inserisci qui la descrizione dell'immagine

inserisci qui la descrizione dell'immagine

inserisci qui la descrizione dell'immagine


3
Fun Markdown fatto - È possibile attivare le immagini in link agli originali: [![image description](SE URL for downsized image)](URL for original image).
Calvin's Hobbies,

1
Potrebbe essere un'idea chiedere alle persone di includere un'immagine "mangiata" di esempio nelle loro risposte.
Nathaniel,

Risposte:


16

C ++, Punteggio: 1,42,042 mila 1,46,766 mila

Questa è essenzialmente una versione leggermente più sofisticata delle due soluzioni esistenti: delle quattro mosse possibili, seleziona quella che massimizza la luminosità. Tuttavia, invece di guardare solo la luminosità del pixel target, esamina la somma ponderata della luminosità del pixel nelle vicinanze del pixel target, in cui i pixel più vicini al target hanno un peso maggiore.

EDIT: l' uso della luminosità non lineare nel calcolo del vicinato migliora leggermente il punteggio.

Compila con g++ joe.cpp -ojoe -std=c++11 -O3 -lcairo. Richiede Cairo.

Corri con joe <image-file> [<radius>]. <image-file>è l'immagine PNG di input. <radius>(argomento facoltativo) è il raggio del vicinato sommato, in pixel (più piccolo è più veloce, più grande è (approssimativamente) migliore). Emette il punteggio e un'immagine denominata out.<image-file>.

#include <cairo/cairo.h>
#include <iostream>
#include <iterator>
#include <algorithm>
#include <string>

using namespace std;

int main(int argc, const char* argv[]) {
    auto* img = cairo_image_surface_create_from_png(argv[1]);
    int width = cairo_image_surface_get_width(img),
        height = cairo_image_surface_get_height(img),
        stride = cairo_image_surface_get_stride(img);
    unsigned char* data = cairo_image_surface_get_data(img);

    double* brightness = new double[width * height];
    double total_brightness = 0;
    for (int y = 0; y < height; ++y) {
        for (int x = 0; x < width; ++x) {
            const unsigned char* p = data + stride * y + 4 * x;
            total_brightness += brightness[y * width + x] = p[0] + p[1] + p[2];
        }
    }

    const int r = argc > 2 ? stoi(argv[2]) : 64, R = 2 * r + 1;
    double* weight = new double[R * R];
    for (int y = -r; y <= r; ++y) {
        for (int x = -r; x <= r; ++x)
            weight[R * (y + r) + (x + r)] = 1.0 / (x*x + y*y + 1);
    }

    auto neighborhood = [&] (int x, int y) {
        double b = 0;
        int x1 = max(x - r, 0), x2 = min(x + r, width - 1);
        int y1 = max(y - r, 0), y2 = min(y + r, height - 1);
        for (int v = y1; v <= y2; ++v) {
            const double *B = brightness + width * v + x1;
            const double *W = weight + R * (v - (y - r)) + (x1 - (x - r));
            for (int u = x1; u <= x2; ++u, ++B, ++W)
                b += (*W) * (*B) * (*B);
        }
        return b;
    };

    int n = (2 * width * height + 3) / 6;
    int x = 0, y = 0;
    double path_brightness = 0;
    int O[][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
    for (int i = 0; i < n; ++i) {
        if (i % 1000 == 0) cerr << (200 * i + n) / (2 * n) << "%\r";

        path_brightness += brightness[width * y + x]; brightness[width * y + x] = 0;
        unsigned char* p = data + stride * y + 4 * x;
        p[0] = p[1] = 16 * i % 255; p[2] = 0;

        auto O_end = partition(begin(O), end(O), [&] (const int* o) {
            return x + o[0] >= 0 && x + o[0] < width &&
                   y + o[1] >= 0 && y + o[1] < height;
        });
        const int* o_max; double o_max_neighborhood = -1;
        for (auto o = O; o != O_end; ++o) {
            double o_neighborhood = neighborhood(x + (*o)[0], y + (*o)[1]);
            if (o_neighborhood > o_max_neighborhood)
                o_max = *o, o_max_neighborhood = o_neighborhood;
        }
        x += o_max[0]; y += o_max[1];
    }

    cout << (path_brightness * width * height) / (n * total_brightness) << endl;

    cairo_surface_write_to_png(img, (string("out.") + argv[1]).c_str());

    delete []brightness;
    delete []weight;
    cairo_surface_destroy(img);
}

risultati

Bridge    1.39945
Balls     1.77714
Scream    1.38349
Fractal   1.31727
Vortex    1.66493
Tornado   1.26366
-----------------
Average   1.46766

ponte Balls Urlare fractal Vortice Tornado

Più piacere per gli occhi

Animazione a vortice Animazione di tornado


Ho appena provato il tuo programma su alcune delle mie immagini di esempio, e una ha molto nero solo attorno al punto di partenza, e lì il tuo programma si arresta in modo anomalo a causa del lambda di quartiere che restituisce NaN.
PlasmaHH,

@PlasmaHH Ti va di condividere l'immagine offensiva?
Ell

Gli stavo dando da mangiare le immagini delle vacanze ... Anche il nero puro 400x400 fa il "trucco".
PlasmaHH,

@PlasmaHH Bene, un'immagine puramente nera ha un punteggio indefinito, è zero su zero, che sarebbe un NaN. Tuttavia, non dovrebbe influire sul calcolo del vicinato o arrestare in modo anomalo il programma (sebbene ciò possa dipendere dall'ambiente in virgola mobile).
Ell

Dai un'occhiata al puntatore o_max if (o_neighborhood > o_max_neighborhood) o_max = *o, o_max_neighborhood = o_neighborhood;solo questo codice lo imposta. tuttavia a causa di nan coinvolti, il confronto è sempre falso, quindi o_max non viene mai impostato e utilizzato non inizializzato.
PlasmaHH,

7

Python 3, punteggio = 1,57

Innanzitutto il nostro serpente viaggia nell'immagine creando linee verticali con uguale distanza l'una dall'altra.

un'

Possiamo estendere questo serpente prendendo due punti uno accanto all'altro in una linea verticale e creando un anello i cui punti finali sono loro.

|      |
|  =>  +----+
|      +----+
|      |

Organizziamo i punti in coppie e per ogni coppia memorizziamo le dimensioni e il valore di luminosità media del loop che dà la massima luminosità media.

Ad ogni passo scegliamo la coppia con il valore più alto estendere il suo loop per ottenere la massima luminosità media sull'estensione e calcolare la nuova dimensione del loop e il valore di luminosità ottimali per la coppia.

Archiviamo le terzine (value, size, point_pair) in una struttura heap ordinate per valore in modo da poter rimuovere l'elemento più grande (in O (1)) e aggiungere il nuovo modificato (in O (log n)) in modo efficiente.

Ci fermiamo quando raggiungiamo il limite di conteggio dei pixel e quel serpente sarà l'ultimo serpente.

La distanza tra le linee verticali ha un effetto molto limitato nei risultati, quindi è stato scelto un costante 40 pixel.

risultati

swirl    1.33084397946
chaos    1.76585674741
fractal  1.49085737611
bridge   1.42603926741
balls    1.92235115238
scream   1.48603818637
----------------------
average  1.57033111819

un' un' un' un' un' un'

Nota: l'immagine originale "The Scream" non era disponibile, quindi ho usato un'altra immagine "The Scream" con una risoluzione simile.

Gif che mostra il processo di estensione del serpente sull'immagine "turbolenza":

un'

Il codice prende uno (o più nomi di file separati dallo spazio) da stdin e scrive le immagini di serpenti risultanti in file png e stampa i punteggi su stdout.

from PIL import Image
import numpy as np
import heapq as hq

def upd_sp(p,st):
    vs,c=0,0
    mv,mp=-1,0
    for i in range(st,gap):
        if p[1]+i<h:
            vs+=v[p[0],p[1]+i]+v[p[0]+1,p[1]+i]
            c+=2
            if vs/c>mv:
                mv=vs/c
                mp=i
    return (-mv,mp)

mrl=[]
bf=input().split()

for bfe in bf:
    mr,mg=0,0    
    for gap in range(40,90,1500):

        im=Image.open(bfe)
        im_d=np.asarray(im).astype(int)

        v=im_d[:,:,0]+im_d[:,:,1]+im_d[:,:,2]

        w,h=v.shape

        fp=[]
        sp=[]
        x,y=0,0
        d=1

        go=True
        while go:
            if 0<=x+2*d<w:
                fp+=[(x,y)]
                fp+=[(x+d,y)]
                sp+=[(x-(d<0),y)]
                x+=2*d
                continue
            if y+gap<h:
                for k in range(gap):
                    fp+=[(x,y+k)]
                y+=gap
                d=-d
                continue
            go=False

        sh=[]
        px=im.load()

        pl=[]

        for p in fp:
            pl+=[v[p[0],p[1]]]
            px[p[1],p[0]]=(0,127,0)   

        for p in sp:
            mv,mp=upd_sp(p,1)
            if mv<=0:
                hq.heappush(sh,(mv,1,mp+1,p))

        empty=False
        pleft=h*w//3
        pleft-=len(fp)
        while pleft>gap*2 and not empty:

            if len(sh)>0:
                es,eb,ee,p=hq.heappop(sh)
            else:
                empty=True
            pleft-=(ee-eb)*2

            mv,mp=upd_sp(p,ee)
            if mv<=0:
                hq.heappush(sh,(mv,ee,mp+1,p))    

            for o in range(eb,ee):
                pl+=[v[p[0],p[1]+o]]
                pl+=[v[p[0]+1,p[1]+o]]
                px[p[1]+o,p[0]]=(0,127,0)   
                px[p[1]+o,p[0]+1]=(0,127,0)

        pl+=[0]*pleft

        sb=sum(pl)/len(pl)
        ob=np.sum(v)/(h*w)

        im.save(bfe[:-4]+'snaked.png')

        if sb/ob>mr:
            mr=sb/ob
            mg=gap

    print(bfe,mr)
    mrl+=[mr]

print(sum(mrl)/len(mrl))

5

Python 2 (punteggio: 0.0797116)

Solo un algoritmo avido molto semplice e ingenuo per far rotolare la palla.

#!/usr/bin/python

from PIL import Image

OFFSETS = [(-1, 0), (0, -1), (1, 0), (0, 1)]
def test_img(filename):
    img = Image.open(filename)

    joe, eaten = (0, 0), []
    img_w, img_h = img.size
    all_pixels = [
        sum(img.getpixel((x, y)))
        for x in xrange(img_w)
        for y in xrange(img_h)
    ]
    total_brightness = float(sum(all_pixels)) / len(all_pixels)

    for _ in xrange(0, (img_w*img_h)/3):
        max_offset, max_brightness = (0, 0), 0
        for o in OFFSETS:
            try:
                brightness = sum(img.getpixel((joe[0] + o[0], joe[1] + o[1])))
            except IndexError:
                brightness = -1
            if brightness >= max_brightness:
                max_offset = o
                max_brightness = brightness

        joe = (joe[0] + max_offset[0], joe[1] + max_offset[1])
        eaten.append(max_brightness)
        img.putpixel(joe, (0, 0, 0))

    eaten_brightness = float(sum(eaten)) / len(eaten)
    print('%d of %d (score %f)' % (eaten_brightness, total_brightness, eaten_brightness / total_brightness))
    img.show()

test_img('img0.jpg')
test_img('img1.png')
test_img('img2.jpg')
test_img('img3.jpg')
test_img('img4.jpg')

Produzione:

llama@llama:~/Code/python/ppcg40069hungrysnake$ ./hungrysnake.py 
15 of 260 (score 0.060699)
9 of 132 (score 0.074200)
16 of 300 (score 0.055557)
4 of 369 (score 0.010836)
79 of 400 (score 0.197266)

1
Penso che il tuo punteggio sia spento. È la media della luminosità di Joe consumata rispetto alla luminosità media dell'intera immagine ... Un Joe a caso dovrebbe ottenere un punteggio di circa 1.
Stretch Maniac,

@StretchManiac Hmm, non vedo nulla di male. sum of brightnesses of eaten pixels / amount of eaten pixelsè la formula giusta, corretta? Forse è solo un algoritmo davvero terribile;)
Maniglia della porta

@Doorknob èThe average brightness of pixels Joe eats / The average brightness of the pixels in the picture*
hmatt1

Per quello arancione e nero swirly (non blu), ho una luminosità media di 68.0846 ... Che non sembra corrispondere a nessuno dei tuoi. Forse la somma (getPixel (...)) non restituisce ciò che vuoi? (Sono un po 'un principiante di pitone). A proposito, ci sono 6 immagini, ma hai solo 5 uscite. Potresti anche etichettare le immagini in qualche modo?
Stretch Maniac,

@StretchManiac Come stai calcolando la tua luminosità? Il mio somma semplicemente i valori R, G e B. Mi dispiace, ho perso quello swirly che arriva penultimo (quello che hai menzionato nel tuo commento, credo). Lo aggiungerò al mattino (ora devo dormire).
Maniglia della porta

5

Java (punteggio: 0.6949)

Un semplice algoritmo che consuma il pixel più luminoso tra i quattro pixel che circondano il pixel corrente. Nel caso di un pareggio, il pixel mangiato è casuale, portando a punteggi diversi e immagini risultanti ogni esecuzione. Pertanto, i punteggi seguenti sono le medie di oltre 50 esecuzioni su ciascuna immagine.

Per eseguirlo, modifica i tre argomenti (esistenti come costanti di classe) nel sorgente o passali tramite riga di comando nel modulo in java HungryImageSnake <source> <iterations> <printScores>cui si <source>trova il file sorgente dell'immagine da mangiare, <iterations>è il numero di volte in cui mangiare l'immagine (prendendo il punteggio medio e il salvataggio del punteggio migliore su tutte le iterazioni), ed <printScores>è vero per stampare il punteggio di ogni iterazione o falso in no.

import javax.imageio.ImageIO;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Random;

public class HungryImageSnake {

    private static final String SOURCE = "tornado.jpg";
    private static final int ITERATIONS = 50;
    private static final boolean PRINT_SCORES = true;

    public static void main(String[] args) {
        try {
            String source = args.length > 0 ? args[0] : SOURCE;
            int iterations = args.length > 1 ? Integer.parseInt(args[1]) : ITERATIONS;
            boolean printScores = args.length > 2 ? Boolean.parseBoolean(args[2]) : PRINT_SCORES;

            System.out.printf("Reading '%s'...%n", source);
            System.out.printf("Performing %d meals...%n", iterations);
            BufferedImage image = ImageIO.read(new File(source));
            double totalScore = 0;
            double bestScore = 0;
            BufferedImage bestImage = null;
            for (int i = 0; i < iterations; i++) {
                HungryImageSnake snake = new HungryImageSnake(image);
                while (snake.isHungry()) {
                    snake.eat();
                }
                double score = snake.getScore();
                if (printScores) {
                    System.out.printf("    %d: score of %.4f%n", i + 1, score);
                }
                totalScore += score;
                if (bestImage == null || score > bestScore) {
                    bestScore = score;
                    bestImage = snake.getImage();
                }
            }
            System.out.printf("Average score: %.4f%n", totalScore / iterations);
            String formattedScore = String.format("%.4f", bestScore);
            String output = source.replaceFirst("^(.*?)(\\.[^.]+)?$", "$1-b" + formattedScore + "$2");
            ImageIO.write(bestImage, source.substring(source.lastIndexOf('.') + 1), new File(output));
            System.out.printf("Wrote best image (score: %s) to '%s'.%n", bestScore, output);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private int x;
    private int y;
    private int movesLeft;
    private int maximumMoves;
    private double eatenAverageBrightness;
    private double originalAverageBrightness;
    private BufferedImage image;

    public HungryImageSnake(BufferedImage image) {
        this.image = copyImage(image);
        int size = image.getWidth() * image.getHeight();
        this.maximumMoves = size / 3;
        this.movesLeft = this.maximumMoves;
        int totalBrightness = 0;
        for (int x = 0; x < image.getWidth(); x++) {
            for (int y = 0; y < image.getHeight(); y++) {
                totalBrightness += getBrightnessAt(x, y);
            }
        }
        this.originalAverageBrightness = totalBrightness / (double) size;
    }

    public BufferedImage getImage() {
        return image;
    }

    public double getEatenAverageBrightness() {
        return eatenAverageBrightness;
    }

    public double getOriginalAverageBrightness() {
        return originalAverageBrightness;
    }

    public double getScore() {
        return eatenAverageBrightness / originalAverageBrightness;
    }

    public boolean isHungry() {
        return movesLeft > 0;
    }

    public void eat() {
        if (!isHungry()) {
            return;
        }
        int[][] options = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
        shuffleArray(options); // prevent snake from getting stuck in corners
        int[] bestOption = null;
        int bestBrightness = 0;
        for (int[] option : options) {
            int optionX = this.x + option[0];
            int optionY = this.y + option[1];
            if (exists(optionX, optionY)) {
                int brightness = getBrightnessAt(optionX, optionY);
                if (bestOption == null || brightness > bestBrightness) {
                    bestOption = new int[]{ optionX, optionY };
                    bestBrightness = brightness;
                }
            }
        }

        image.setRGB(bestOption[0], bestOption[1], 0);
        this.movesLeft--;
        this.x = bestOption[0];
        this.y = bestOption[1];
        this.eatenAverageBrightness += bestBrightness / (double) maximumMoves;
    }

    private boolean exists(int x, int y) {
        return x >= 0 && x < image.getWidth() && y >= 0 && y < image.getHeight();
    }

    private int getBrightnessAt(int x, int y) {
        int rgb = image.getRGB(x, y);
        int r = (rgb >> 16) & 0xFF;
        int g = (rgb >> 8) & 0xFF;
        int b = rgb & 0xFF;
        return r + g + b;
    }

    private static <T> void shuffleArray(T[] array) {
        Random random = new Random();
        for (int i = array.length - 1; i > 0; i--) {
            int index = random.nextInt(i + 1);
            T temp = array[index];
            array[index] = array[i];
            array[i] = temp;
        }
    }

    private static BufferedImage copyImage(BufferedImage source){
        BufferedImage b = new BufferedImage(source.getWidth(), source.getHeight(), source.getType());
        Graphics g = b.getGraphics();
        g.drawImage(source, 0, 0, null);
        g.dispose();
        return b;
    }
}

Punteggi medi, per immagine, oltre cinquanta iterazioni:

Bridge - 0.7739
Spheres - 0.5580
Scream - 0.8197
Fractal - 0.3850
Vortex - 0.9158
Tornado - 0.7172

Migliori punteggi, per immagine, nelle stesse cinquanta iterazioni:

Bridge - 0.8996
Spheres - 0.8741
Scream - 0.9183
Fractal - 0.5720
Vortex - 1.1520
Tornado - 0.9281

Immagini delle piste con il punteggio più alto:

Bridge - 0.8996 Sfere - 0,8741 Scream - 0.9183 Frattale - 0,5720 Vortice - 1.1520 Tornado - 0.9281

Come è evidente dalle immagini, molto meno di un terzo dei pixel viene effettivamente mangiato, poiché il serpente si blocca di tanto in tanto tra i pixel che ha già mangiato, a cui rimane bloccato nell'area morta fino a quando la casualità dei suoi movimenti lo porta a una porzione commestibile dell'immagine.

Inoltre, a causa del consumo di pixel da parte del serpente, i punteggi sono distorti verso il basso, poiché la luminosità zero dei pixel morti viene nuovamente calcolata nella media. Mi aspetterei di vedere punteggi molto più alti se l'algoritmo di punteggio fosse modificato per dividere solo per il numero di mosse che hanno portato a mangiare nuovi pixel, piuttosto che per tutte le mosse (incluse quelle in cui il serpente mangia un pixel ormai morto che ha già mangiato prima ).

Naturalmente, un approccio migliore sarebbe quello di creare una sorta di euristica della luminosità per ogni pixel e trovare il percorso dei width * height / 3pixel con la luminosità media più alta, ma dubito che questo approccio sarà ottimale in tempo di esecuzione, specialmente su immagini più grandi, come il numero di possibili permutazioni sarebbe molto grande. In un secondo momento potrei prendere una decisione su questa forma e postarla in una risposta separata in tal caso.


Se qualcuno è infastidito da quanto è grande la mia risposta (a causa delle immagini in essa), fammi sapere e rimuoverò le immagini a favore di collegamenti o un'altra alternativa meno spacy. Oppure, se qualcuno desidera gli originali a piena risoluzione di qualsiasi immagine "mangiata", fammelo sapere anche in un commento.
FThompson,

4

Python 2, Punteggio: 1.205

Qualche tempo fa ho messo insieme una rapida soluzione Python ma ho dimenticato di pubblicarla. Ecco qui. Trova i blocchi più ricchi nell'immagine, quindi viaggia verso ciascun blocco, mangiando tutti i blocchi migliori a cui arriva.

risultati

bridge.jpg: 591.97866/515.41501 =                               1.14855 
BallsRender.png: 493.24711/387.80635 =                          1.27189 
Mandel_zoom_04_seehorse_tail.jpg: 792.23990/624.60579 =         1.26838 
Red_Vortex_Apophysis_Fractal_Flame.jpg: 368.26121/323.08463 =   1.13983 
The_Scream.jpg: 687.18565/555.05221 =                           1.23806
swirl.jpg: 762.89469/655.73767 =                                1.16341

AVERAGE                                                         1.205

Foto di esempio

Immagine del ponte elaborata

Codice Python 2.7

from pygame.locals import *
import pygame, sys, random

fn = sys.argv[1]

screen = pygame.display.set_mode((1900,1000))
pic = pygame.image.load(fn)
pic.convert()
W,H = pic.get_size()
enough = W*H/3
screen.blit(pic, (0,0))

ORTH = [(-1,0), (1,0), (0,-1), (0,1)]
def orth(p):
    return [(p[0]+dx, p[1]+dy) for dx,dy in ORTH]

def look(p):
    x,y = p
    if 0 <= x < W and 0 <= y < H:
        return sum(pic.get_at(p))
    else:
        return -1

# index picture
locs = [(x,y) for x in range(W) for y in range(H)]
grid = dict( (p,sum(pic.get_at(p))) for p in locs )
rank = sorted( grid.values() )
median = rank[ len(rank)/2 ]
dark = dict( (k,v) for k,v in grid if v < median )
good = dict( (k,v) for k,v in grid if v > median )
pictotal = sum(rank)
picavg = 1.0 * pictotal/(W*H)
print('Indexed')

# compute zone values:
block = 16
xblocks, yblocks = (W-1)/block, (H-1)/block
zones = dict( ((zx,zy),0) for zx in range(xblocks) for zy in range(yblocks) )
for x,y in locs:
    div = (x/block, y/block)
    if div in zones:
        colsum = sum( pic.get_at((x,y)) )
        zones[div] += colsum

# choose best zones:
zonelist = sorted( (v,k) for k,v in zones.items() )
cut = int(xblocks * yblocks * 0.33)
bestzones = dict( (k,v) for v,k in zonelist[-cut:] )

# make segment paths:
segdrop = [(0,1)] * (block-1)
segpass = [(1,0)] * block
segloop = [(0,-1)] * (block-1) + [(1,0)] + [(0,1)] * (block-1)
segeat = ( segloop+[(1,0)] ) * (block/2)
segshort = [(1,0)] * 2 + ( segloop+[(1,0)] ) * (block/2 - 1)

def segtopath(path, seg, xdir):
    for dx,dy in seg:
        x,y = path[-1]
        newloc = (x+dx*xdir, y+dy)
        path.append(newloc)

# design good path:
xdir = 1
path = [(0,0)]
segtopath(path, segdrop, xdir)
shortzone = True
while True:
    x,y = path[-1]
    zone = (x/block, y/block)
    if zone in bestzones:
        if shortzone:
            seg = segshort
        else:
            seg = segeat
    else:
        seg = segpass
    segtopath(path, seg, xdir)
    shortzone = False
    # check end of x block run:
    x,y = path[-1]
    zone = (x/block, y/block)
    if not ( 0 <= x < xblocks*block ):
        del path[-1]
        segtopath(path, segdrop, xdir)
        shortzone = True
        xdir = xdir * -1
    if len(path) > enough:
        break
print('Path Found')

# show path on picture:
loc = path.pop(0)
eaten = 1
joetotal = grid[loc]
i = 0
while eaten <= enough:
    loc = path[i]
    i += 1
    pic.set_at(loc, (0,0,0))
    joetotal += grid[loc]
    eaten += 1
    if i % 1000 == 0:
        screen.blit(pic, (0,0))
        pygame.display.flip()
        for event in pygame.event.get():
            if event.type == QUIT: sys.exit(0)

# save picture and wait:
screen.blit(pic, (0,0))
pygame.display.flip()
pygame.image.save(pic, 'output/'+fn)
joeavg = 1.0 * joetotal/eaten
print '%s: %7.5f/%7.5f = %7.5f' % (fn, joeavg, picavg, joeavg/picavg)
while True:
    for event in pygame.event.get():
        if event.type == QUIT: sys.exit(0)
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.