Programming Assignment 1: Percolation

Percolation

实现Percolation模型。
用蒙特卡罗模拟估计渗滤阈值的值。

关于backwash问题:有了一个虚拟底层位置,如果网格已经渗透了。这时判断其中一个位置(与底部相连,并且底部是打开的,与虚拟底层位置相连)是否满(即与虚拟顶层位置是相连的),那么不管这个位置是不是真的满,结果总会是满的。因为网格已经渗透了,那么虚拟顶层位置与虚拟底层位置总是相连的,而这个位置与虚拟顶层位置是相连的,这时候再判断它是不是满(与虚拟顶层位置相连),结果当然总是为真。
回流问题

这里提供了两种方法解决backwash,即回流问题

Percolation with top virtual site

即带有虚拟位置的网格。
同时需要建立两个WeightedQuickUnionUF 对象,一个同时有虚拟顶层位置和虚拟底层位置,这样判断是否渗透很容易。另一个只有虚拟顶层位置,这就避免了回流问题,用来判断是否满。
由于建立了两个WeightedQuickUnionUF 对象,所以 内存使用没有完全过关,得到了97分。

Percolation.java

import edu.princeton.cs.algs4.StdIn;
import edu.princeton.cs.algs4.StdOut;
import edu.princeton.cs.algs4.WeightedQuickUnionUF;

/**
 * The {@code Percolation} class provides methods for calculating the Percolation. 
 * <p>
 * Creates two WeightedQuickUnionUF objects to solve the backwash problem.
 * 
 * @author zhangyu
 * @date 2017.2.27
 */
public class Percolation 
{
    private int size; // size of created grid
    private int[] status; // record the status of each site
    private WeightedQuickUnionUF grid;
    private WeightedQuickUnionUF gridNoVBottom;

    /**
     * Initializes two WeightedQuickUnionUF object. One has two 
     * virtual sites, and the other one has only one top site. 
     * Set state of each site blocked.
     * 
     * @param  n size of created grid
     * @throws IllegalArgumentException if n < 1
     */
    public Percolation(int n)
    {
        if (n < 1) throw new IllegalArgumentException("Grid size out of range");
        size = n;
        status = new int[n * n];
        for (int i = 0; i < n * n; i++) status[i] = 0;
        grid = new WeightedQuickUnionUF(n*n + 2);
        gridNoVBottom = new WeightedQuickUnionUF(n*n + 1);
    }

    /**
     * open site (row, col) if it is not open already.
     * 
     * @param row abscissa of the grid 
     * @param col ordinate of the grid
     */
    public void open(int row, int col)
    {
        int idx = xyTo1D(row, col);

        validate(row, col);
        status[idx] = 1;
        if (1 == row) // connect to the virtual site
        {
            grid.union(idx, size * size);
            gridNoVBottom.union(idx, size * size);
        }
        if (size == row) grid.union(idx, size*size + 1);

        int[] xDiff = {-1, 1, 0, 0};
        int[] yDiff = {0, 0, -1, 1};

        for (int i = 0; i < 4; i++)
        {
            int adjX = row + xDiff[i];
            int adjY = col + yDiff[i];

            if (adjX > 0 && adjX <= size)
            {
                if (adjY > 0 && adjY <= size)
                {
                    int adjPosIdx = xyTo1D(adjX, adjY);
                    if (1 == status[adjPosIdx])
                    {
                        grid.union(idx, adjPosIdx);
                        gridNoVBottom.union(idx, adjPosIdx);
                    }
                }
            }
        }
    }

    /**
     * Determine whether the site (row, col) is open.
     * 
     * @param row abscissa of the grid 
     * @param col ordinate of the grid
     * @return true if the site (row, col) is open;
     *         false otherwise
     */
    public boolean isOpen(int row, int col)
    {
        validate(row, col);
        return status[xyTo1D(row, col)] == 1;
    }

    /**
     * Determine whether the site (row, col) is full.
     * 
     * @param row abscissa of the grid 
     * @param col ordinate of the grid
     * @return true if the site (row, col) is full;
     *         false otherwise
     */
    public boolean isFull(int row, int col)
    {
        validate(row, col);
        return isOpen(row, col) && gridNoVBottom.connected(xyTo1D(row, col), size * size);
    }

    /**
     * Returns the number of open sites.
     * 
     * @return the number of open sites
     */
    public int numberOfOpenSites()
    {
        int sum = 0;

        for (int i = 0; i < status.length; i++) sum += status[i];
        return sum;
    }

    /**
     * Determine whether the grid percolates.
     * 
     * @return true if the grid percolates.
     *         false otherwise
     */
    public boolean percolates()
    {
        return grid.connected(size * size, size*size + 1);
    }

    //map 2D coordinates to 1D coordinates 
    private int xyTo1D(int row, int col)
    {
        return (row - 1)*size + col - 1;
    }

    // validate that (row, col) is valid
    private void validate(int row, int col)
    {
        if (row < 1 || row > size || col < 1 || col > size) 
            throw new IndexOutOfBoundsException("index: (" + row + ", " + col + ") are out of bounds");
    }

    /**
     * Unit tests the {@code Percolation} data type.
     *
     * @param args the command-line arguments
     */
    public static void main(String[] args)
    {
        int n = StdIn.readInt();
        Percolation client = new Percolation(n);
        while (!StdIn.isEmpty())
        {
            int row = StdIn.readInt();
            int col = StdIn.readInt();
            client.open(row, col);
            StdOut.println(client.isOpen(row, col));
            StdOut.println(client.isFull(row, col));
            StdOut.println(client.percolates());
        }
    }
}
ASSESSMENT SUMMARY

Compilation: PASSED
API: PASSED

Findbugs: PASSED
Checkstyle: FAILED (2 warnings)

Correctness: 26/26 tests passed
Memory: 5/8 tests passed
Timing: 9/9 tests passed

Aggregate score: 96.25%
[Compilation: 5%, API: 5%, Findbugs: 0%, Checkstyle: 0%, Correctness: 60%, Memory: 10%, Timing: 20%]

Percolation without virtual sites

不带虚拟位置的网格。
只建立一个WeightedQuickUnionUF 对象,没有虚拟位置。使用很多标签来判断打开,阻塞,与顶部相连,与底部相连和渗透这几种状态。当一个位置与顶部相连,就是满状态,当它既是与顶部相连,又是与底部相连,这个网格就是渗透的。在打开一个位置时,就同时更新他们的状态,如果相邻的位置是打开的,那么除了合并区域使它们相连,还要互相将状态进行或操作,即每个位置得到相邻位置的状态,为了使每个部分的位置的状态都能更新,就必须更新根位置的状态。
由于使用的是字节类型和或操作。所以内存使用的不多(少了一个WeightedQuickUnionUF 对象),得到了一个bonus:),100分。

Percolation.java

import edu.princeton.cs.algs4.StdIn;
import edu.princeton.cs.algs4.StdOut;
import edu.princeton.cs.algs4.WeightedQuickUnionUF;

/**
 * The {@code Percolation} class provides methods for calculating the Percolation.
 * <p>
 * Creates only one WeightedQuickUnionUF object to solve the backwash problem.
 * 
 * @author zhangyu
 * @date 2017.2.27
 */
public class Percolation 
{
    private static final byte BLOCKED         = Byte.valueOf("0"); // 00000000
    private static final byte OPEN            = Byte.valueOf("1"); // 00000001
    private static final byte TOPCONNECTED    = Byte.valueOf("2"); // 00000010
    private static final byte BOTTOMCONNECTED = Byte.valueOf("4"); // 00000100
    private static final byte PERCOLATED      = Byte.valueOf("7"); // 00000111
    private int size; // size of created grid
    private byte[] state; // record the state of each site
    private int openSites; // number of open sites
    private boolean percolate = false;
    private WeightedQuickUnionUF grid;

    /**
     * Initializes one WeightedQuickUnionUF object, without 
     * any virtual site. Set state of each site blocked.
     * 
     * @param  n size of created grid
     * @throws IllegalArgumentException if n < 1
     */
    public Percolation(int n) // create n-by-n grid, with all sites blocked
    {
        if (n < 1) throw new IllegalArgumentException("Grid size out of range");
        size = n;
        state = new byte[n * n];
        for (int i = 0; i < n * n; i++) state[i] = BLOCKED;
        grid = new WeightedQuickUnionUF(n * n);
    }

    /**
     * open site (row, col) if it is not open already.
     * 
     * @param row abscissa of the grid 
     * @param col ordinate of the grid
     */
    public void open(int row, int col)
    {
        validate(row, col);

        int idx = xyTo1D(row, col);
        int[] xDiff = {-1, 1, 0, 0};
        int[] yDiff = {0, 0, -1, 1};

        // if the site has been opened, then return
        if (0 != (state[idx] & OPEN)) return;
        state[idx] = (byte)(state[idx] | OPEN);
        if (1 == row)    state[idx] = (byte)(state[idx] | TOPCONNECTED);
        if (size == row) state[idx] = (byte)(state[idx] | BOTTOMCONNECTED);

        for (int i = 0; i < 4; i++)
        {
            int adjX = row + xDiff[i];
            int adjY = col + yDiff[i];

            if (adjX > 0 && adjX <= size)
            {
                if (adjY > 0 && adjY <= size)
                {
                    int adjSiteIdx = xyTo1D(adjX, adjY); // index of the adjacent site
                    int rootASIdx = grid.find(adjSiteIdx);

                    if (OPEN == (state[adjSiteIdx] & OPEN)) // if the adjacent site is open
                    {
                        state[idx] = (byte)(state[idx] | state[rootASIdx]);
                        grid.union(idx, adjSiteIdx); // union the two components
                    }
                }
            }
        }

        int rootIdx = grid.find(idx); // must get root index after union operation

        state[rootIdx] = (byte)(state[rootIdx] | state[idx]);
        if (PERCOLATED == (byte)(state[rootIdx] & PERCOLATED))
            percolate = true;
        openSites++;
    }

    /**
     * Determine whether the site (row, col) is open.
     * 
     * @param row abscissa of the grid 
     * @param col ordinate of the grid
     * @return true if the site (row, col) is open;
     *         false otherwise
     */
    public boolean isOpen(int row, int col)
    {
        validate(row, col);
        return OPEN == (state[xyTo1D(row, col)] & OPEN);
    }

    /**
     * Determine whether the site (row, col) is full.
     * 
     * @param row abscissa of the grid 
     * @param col ordinate of the grid
     * @return true if the site (row, col) is full;
     *         false otherwise
     */
    public boolean isFull(int row, int col)
    {
        validate(row, col);

        int rootIdx = grid.find(xyTo1D(row, col)); // root index of given site (row, col)
        return isOpen(row, col) && TOPCONNECTED == (state[rootIdx] & TOPCONNECTED);
    }

    /**
     * Returns the number of open sites.
     * 
     * @return the number of open sites
     */
    public int numberOfOpenSites()
    {
        return openSites;
    }

    /**
     * Determine whether the grid percolates.
     * 
     * @return true if the grid percolates.
     *         false otherwise
     */
    public boolean percolates()
    {
        return percolate;
    }

    //map 2D coordinates to 1D coordinates 
    private int xyTo1D(int row, int col)
    {
        return (row - 1)*size + col - 1;
    }

    // validate that (row, col) is valid
    private void validate(int row, int col)
    {
        if (row < 1 || row > size || col < 1 || col > size) 
            throw new IndexOutOfBoundsException("index: (" + row + ", " + col + ") are out of bounds");
    }

    /**
     * Unit tests the {@code Percolation} data type.
     *
     * @param args the command-line arguments
     */
    public static void main(String[] args)
    {
        int n = StdIn.readInt();
        Percolation client = new Percolation(n);

        while (!StdIn.isEmpty())
        {
            int row = StdIn.readInt();
            int col = StdIn.readInt();
            client.open(row, col);
            StdOut.println(client.isOpen(row, col));
            StdOut.println(client.isFull(row, col));
            StdOut.println(client.percolates());
        }
    }
}
ASSESSMENT SUMMARY

Compilation: PASSED
API: PASSED

Findbugs: PASSED
Checkstyle: FAILED (8 warnings)

Correctness: 26/26 tests passed
Memory: 9/8 tests passed
Timing: 9/9 tests passed   

Aggregate score: 101.25%  
[Compilation: 5%, API: 5%, Findbugs: 0%, Checkstyle: 0%, Correctness: 60%, Memory: 10%, Timing: 20%]

PercolationStats.java

import edu.princeton.cs.algs4.StdIn;
import edu.princeton.cs.algs4.StdOut;
import edu.princeton.cs.algs4.StdRandom;
import edu.princeton.cs.algs4.StdStats;

/**
 * The {@code PercolationStats} class performs independent experiment, using 
 * the Percolation data structure. Then compute the mean and standard 
 * deviation of results.
 * <p>
 * It also provides method to compute confidence intervals for them.
 * 
 * @author zhangyu
 * @date 2017.2.27
 */
public class PercolationStats 
{
    private int trials;
    private double[] threshold;

    /**
     * perform trials independent experiments on an n-by-n grid
     * 
     * @param  n size of created grid
     * @param  trials times of experiments
     * @throws IllegalArgumentException unless
     *         both grid size and value of trials out of range
     */
    public PercolationStats(int n, int trials)
    {   
        if (n < 1) 
            throw new IllegalArgumentException("Grid size out of range");
        if (trials < 1) 
            throw new IllegalArgumentException("value of trials out of range");
        this.trials = trials;
        threshold = new double[trials];
        for (int i = 0; i < trials; i++)
        {
            Percolation expModel = new Percolation(n);

            while (!expModel.percolates())
            {
                int row = StdRandom.uniform(n) + 1;
                int col = StdRandom.uniform(n) + 1;

                expModel.open(row, col);
            }
            threshold[i] = (double)expModel.numberOfOpenSites() / (double)(n*n);
        }
    }

    /**
     * Returns the sample mean of percolation threshold.
     * 
     * @return the sample mean of percolation threshold
     */
    public double mean()
    {
        return StdStats.mean(threshold);
    }

    /**
     * Returns the sample standard deviation of percolation threshold.
     * 
     * @return the sample standard deviation of percolation threshold
     */
    public double stddev()
    {
        return StdStats.stddev(threshold);
    }

    /**
     * Returns the low endpoint of 95% confidence interval.
     * 
     * @return the low endpoint of 95% confidence interval.
     */
    public double confidenceLo()
    {
        return mean() - 1.96*stddev() / Math.sqrt(trials);
    }

    /**
     * Returns the high endpoint of 95% confidence interval.
     * 
     * @return the high endpoint of 95% confidence interval.
     */
    public double confidenceHi()
    {
        return mean() + 1.96*stddev() / Math.sqrt(trials);
    }

    /**
     * Unit tests the {@code PercolationStats} data type.
     *
     * @param args the command-line arguments
     */
    public static void main(String[] args)
    {
        int n, trials;

        n = StdIn.readInt();
        trials = StdIn.readInt();
        PercolationStats client = new PercolationStats(n, trials);
        StdOut.println("mean                    = " + client.mean());
        StdOut.println("stddev                  = " + client.stddev());
        StdOut.println("95% confidence interval = " + "[" + client.confidenceLo() + ", " 
                                                    + client.confidenceHi() + "]");
    }
}
参考我的github
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值