Schlagwort-Archiv: Software

Roman Numbers Converter

package de.sambalmueslie.number_convert;

import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class RomanNumberConverter implements NumberConverter {

	private class MappingEntry {

		public MappingEntry(final int number, final char symbol) {
			this(number, symbol, false);
		}

		public MappingEntry(final int number, final char symbol, final boolean subtractable) {
			this.number = number;
			this.symbol = symbol;
			this.subtractable = subtractable;
		}

		private final int number;
		private final boolean subtractable;
		private final char symbol;
	}

	public RomanNumberConverter() {
		mappings.add(new MappingEntry(1, 'I', true));
		mappings.add(new MappingEntry(5, 'V'));
		mappings.add(new MappingEntry(10, 'X', true));
		mappings.add(new MappingEntry(50, 'L'));
		mappings.add(new MappingEntry(100, 'C', true));
		mappings.add(new MappingEntry(500, 'D'));
		mappings.add(new MappingEntry(1000, 'M'));
	}

	@Override
	public String convert(final int value) {
		final StringBuffer result = new StringBuffer();

		int remaining = value;

		final int start = mappings.size() - 1;
		for (int index = start; index >= 0; index--) {
			final MappingEntry current = mappings.get(index);
			final MappingEntry next = index > 0 ? mappings.get(index - 1) : null;
			final MappingEntry doubleNext = index > 1 ? mappings.get(index - 2) : null;

			final int number = current.number;
			final boolean matches = remaining >= number;
			if (matches) {
				final int amount = remaining / number;
				result.append(concat(current.symbol, amount));
				remaining -= number * amount;
			} else if (next != null && next.subtractable && remaining >= number - next.number) {
				result.append(next.symbol + "" + current.symbol);
				remaining -= number - next.number;
			} else if (doubleNext != null && doubleNext.subtractable && remaining >= number - doubleNext.number) {
				result.append(doubleNext.symbol + "" + current.symbol);
				remaining -= number - doubleNext.number;
			}

		}
		return result.toString();
	}

	@Override
	public int convert(final String value) {
		final List<Integer> numbers = value.chars().map(t -> find(t).number).boxed().collect(Collectors.toList());
		for (int i = 0; i < numbers.size() - 1; i++) {
			if (numbers.get(i) < numbers.get(i + 1)) {
				numbers.set(i, numbers.get(i) * -1);
			}
		}
		return numbers.stream().mapToInt(t -> t).sum();
	}

	private String concat(final char c, final int amount) {
		final StringBuffer sb = new StringBuffer();
		Stream.generate(() -> c).limit(amount).forEach(t -> sb.append(t));
		return sb.toString();
	}

	private MappingEntry find(final Integer c) {
		final Optional<MappingEntry> result = mappings.stream().filter(n -> n.symbol == c).findFirst();
		return result.isPresent() ? result.get() : null;
	}

	private final List<MappingEntry> mappings = new LinkedList<>();
}

My personal vision of testing software

There are several different practices and scopes of software testing but I will focus on testing during development. If you work in a very small project or alone on a piece of software, it could be easier to test your software by click around on the ui and check if it works how it should. But if things go a little bit bigger this style of testing produces some huge problems:

  1. Deploying your software and click around on the gui takes a lot of time.
  2. There are no regressions, if your feature works and you work on the next one, the first would be broken and if you forget to try it out again your software fail.
  3. There is no possibility to let the tests executed by some continuous integration server like Jenkins for example.

So if your code reaches a couple of lines, high quality work without testing would be nearly impossible or takes a lot of time until it works and if you change it a little bit it could end up in a mess very fast. But when you start this looks very simple and straight forward. It’s a little bit like a jenga tower. You build it up and checked everything. Let’s imagine it works and your customer is satisfied, but what if he wants some minor changes. Every change is like pull out a piece of the tower. If you change it enough times, he will fall down. So therefore you need something reliable which guarantees you, that your changes only produces the result your customer wants and not changing anything else. But how could you deal with it, if you have a lot of pressure and your schedule is very tight?

My personal vision of testing software weiterlesen

Java Sinus Generator

package de.sambalmueslie.sine_generator;

/**
 * Generate a sine.
 * 
 * Copyright (C) 2012 Oliver Eckle
 * 
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <http://www.gnu.org/licenses/>.
 * 
 */
public class SineGenerator {

	/** the maximum samples per oscillation. */
	private static final int MAX_SAMPLES_PER_OSCILLATION = 160;
	/** the minimum samples per oscillation. */
	private static final int MIN_SAMPLES_PER_OSCILLATION = 2;

	/**
	 * Constructor.
	 * 
	 * @param theSampleRate
	 *            the sample rate
	 * @param theMaximumAmplitude
	 *            the maximum amplitude
	 */
	public SineGenerator(final int theSampleRate,
			final short theMaximumAmplitude) {
		sampleRate = theSampleRate;
		maximumAmplitude = theMaximumAmplitude;
	}

	/**
	 * Generate sine oscillation samples for a defined total length.
	 * 
	 * @param frequency
	 *            the freqency
	 * @param totalSamples
	 *            the total samples
	 * @return the result
	 */
	public short[] generateSineOscillationSamples(final int frequency,
			final int totalSamples) {
		final short[] result = new short[totalSamples];
		final short[] singleResult = generateSingleSineOscillationSamples(frequency);
		for (int i = 0; i < totalSamples; i++) {
			final int j = i % singleResult.length;
			result[i] = singleResult[j];
		}
		return result;
	}

	/**
	 * Generate the samples for one single sine oscillation.
	 * 
	 * @param frequency
	 *            the frequency
	 * @return the generated samples
	 */
	public short[] generateSingleSineOscillationSamples(final int frequency) {
		final int samples = calculateSamplesPerOscillation(frequency);
		final short[] result = new short[samples];
		final int samplesMiddle = samples / 2;
		for (int i = 0; i < samples; i++) {
			if (i < samplesMiddle) {
				final double c = (i == 0) ? 0 : 2 * Math.PI * i / samples;
				final double sineVal = Math.sin(c);
				result[i] = (short) (sineVal * maximumAmplitude);
			} else {
				result[i] = (short) (result[i - samplesMiddle] * -1);
			}
		}
		return result;
	}

	/**
	 * Calculate the total samples per oscillation.
	 * 
	 * @param frequency
	 *            the frequency
	 * @return the calculated samples
	 */
	private int calculateSamplesPerOscillation(final int frequency) {
		if (frequency <= 0) {
			return MAX_SAMPLES_PER_OSCILLATION;
		}
		final int samples = sampleRate / frequency;
		if (samples > MAX_SAMPLES_PER_OSCILLATION) {
			return MAX_SAMPLES_PER_OSCILLATION;
		} else if (samples < MIN_SAMPLES_PER_OSCILLATION) {
			return MIN_SAMPLES_PER_OSCILLATION;
		}
		return samples;
	}

	/** the amplitude. */
	private final int maximumAmplitude;
	/** the sample rate. */
	private final int sampleRate;

}

 

SineGenerator