Finding the nth term in a sequence - java

I have a sequence, and I am trying to make a program to find the nth term of the sequence.
The sequence is as follows:
1, 11, 21, 1211, 111221, 312211...
In this sequence, each term describes the previous term. For example, "1211" means that the previous term; the previous term is "21" where there is one occurrence of a 2 and then one occurrence of a 1 (=1211). To get the third term, "21," you look at the second term: 11. There are two occurrences of a 1 which gives us "21."
import java.util.*;
class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
System.out.println( Main.num(n-1, "1"));
}
public static String num(int times, String x){
if(times == 0){
return x;
}else{
//System.out.println("meow");
String y = "" + x.charAt(0);
int counter = 0;
for(int i = 1; i < x.length(); i++){
if(x.charAt(i) == x.charAt(i-1)){
counter++;
}else{
y += "" + counter + x.charAt(i-1);
counter = 0;
}
}
return num(times--, y);
}
//return "";
}
}
My code uses recursion to find the nth term. But, it gives us errors :(
First, I start of the method "num" by passing it the number of terms-1 (since the first term is already given) and the first term (1).
In the method num, we start off by using a conditional to establish the base case (when you are done finding the nth term).
If the base case is false, then you find the next term in the sequence.

This is a very cool sequence! I like that it is English based and not mathematical, haha. (Though now I wonder ... is there a formula we could make for the nth term? I'm pretty sure it's impossible or uses some crazy-level math, but just something to think about ...)
In your solution, the recursive logic of your code is correct: after you find each term, you repeat the method with your knew number and find the next term using that element, and end when you have determined the first n elements. Your base case is also correct.
However, the algorithm you developed for determining the terms in the sequence is the issue.
To determine the next element in the sequence, we want to:
Logical Error:
Create a empty variable, y, for your next element. The variable, counter, should not start at 0, however. This is because every element will ALWAYS have an occurrence of at least 1, so we should initialize int counter = 1;
Iterate through the characters in x. (You did this step correctly) We begin at i = 1, because we compare each character to the previous one.
If the current character is equal to the previous character, we increment counter by 1.
Otherwise, we concatenate counter and the character being repeated, to y. Remember, to reinitialize counter to 1, not 0.
Technical Errors:
Once we reach the end of iterating x, we need to concatenate our final counter and character to y, since the else statement for the final characters will never run in our for loop.
This is done with the following code: y += "" + counter + x.charAt(x.length() - 1);
Finally, when you are doing your recursive call, you should do --times instead of times--. The difference between these two parameters is that with your original code, you are post-decrementing. This means the value of times is decreasing after the method call, when we want the decreased value to be sent into the method. To solve this, we need to pre-decrement, by doing --times.
import java.util.*;
class CoolSequence {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
System.out.println(num(n, "1"));
}
public static String num(int times, String x){
if(times == 0){
return x;
}
else{
String y = "";
int counter = 1;
for(int i = 1; i < x.length(); i++){
if(x.charAt(i) == x.charAt(i - 1)){
counter++;
}
else{
y += "" + counter + x.charAt(i - 1);
counter = 1;
}
}
y += "" + counter + x.charAt(x.length() - 1);
return num(--times, y);
}
}
}
Testing:
6
13112221
An alternative approach would be using an iterative method:
import java.util.*;
class CoolSequence2 {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
ArrayList<String> nums = new ArrayList<String>();
int n = scan.nextInt();
String val = "1";
for(int i = 0; i < n; i++){
String copy = val;
val = "";
while(!copy.equals("")){
char curr = copy.charAt(0);
int ind = 0;
int cons = 0;
while(ind < copy.length() && curr == copy.charAt(ind)){
cons += 1;
ind += 1;
}
val += String.valueOf(cons) + copy.charAt(cons - 1);
copy = copy.substring(cons);
}
nums.add(val);
}
System.out.println(nums.get(nums.size() - 1));
}
}
6
13112221
In this method, we use a for loop to iterate through n terms. To determine each element, we do a similar method to your logic:
We create an empty string, val, to hold the new element, and store our current element in copy. We also initialize a cons, similar to your counter.
While copy is not empty, we iterate through copy and increment cons until there is an element that is not equal to the next element.
When this occurs, we concatenate cons and the repeated element to val, like in your code. Then, we cut out the repeated elements from copy and continue the process.
We add the new value of val to nums, and keep iterating through the n elements.
I hope these two methods of approaching your problem helped! Please let me know if you have any further questions or clarifications :)

You can use Pattern with backreference.
The regular expression "(.)\\1*" matches any single character ("(.)") and zero or more sequences of the same character ("\\1*"). "\\1" is called a backreference, it refers to the string enclosed in parentheses 1st.
For example, it matches 111, 22 and 1 for 111221.
replaceAll() calls the lambda expression specified by the argument each time it matches. The lambda expression receives a MatchResult and returns a string. The matched string is replaced with the result.
The lambda expression in this case concatenates the length of the matched string (match.group().length()) and the first character (match.group(1)).
static final Pattern SEQUENCE_OF_SAME_CHARACTER = Pattern.compile("(.)\\1*");
static String num(int times, String x) {
for (int i = 0; i < times; ++i)
x = SEQUENCE_OF_SAME_CHARACTER.matcher(x).replaceAll(
match -> match.group().length() + match.group(1));
return x;
}
public static void main(String[] args) {
for (int i = 1; i <= 8; ++i)
System.out.print(num(i - 1, "1") + " ");
}
output:
1 11 21 1211 111221 312211 13112221 1113213211

Related

Program entering in a infinite loop only with a specific value

I just started with java and while was doing an exercise about permutations (the exercise asked to create a permutation of N elements using an array a[] meeting the requirement that no a[i] is equal to i.) I've created the following code. While testing it, I realized that it entered in a infinite loop sometimes when N = 6 specifically.
Any thoughts on where is the problem?
public class GoodPerm {
public static void main(String arg[]) {
int n = Integer.parseInt(arg[0]);
int[] guests = new int[n];
for (int i = 0; i < n; i++) {
guests[i] = i;
}
for (int i = 0; i < n; i++) {
int r = i + (int) (Math.random() * (n - i));
int q = guests[r];
guests[r] = guests[i];
guests[i] = q;
if(guests[i] == i){
i --;
}
}
for(int q : guests){
System.out.println(q);
}
}
}
Maybe the code enters in a inf-loop in another values, but I didn't found any others.
This code can always enter an inf-loop. As I understand the code, you try to do some random switches to achieve your needed result. But if the last element of your array has never been switched, it won't be possible to switch it to any "later/higher" position (because there are no more). In the "last" iteration of your second for-loop (so i + 1 == n holds at the beginning) r will always evaluate to i thus no real switch happens. If the last element is still in place, you gonna repeat this forever.

Find missing term in arithmetic progression -

So I'm working on this programming challenge online where I'm supposed to write a program that finds the missing term in an arithmetic progression. I solved the problem in two ways: one that used summing all the given terms of the progression and then subtracting that from the sum of the actual progression. My other solution was based on finding the difference of the progression, and then using that difference in a for loop to find the missing term. While my first solution successfully passes all test cases, my second solution fails two out of the 7 test cases. The challenge doesn't allow anyone to see their test cases so I had no idea what was wrong. Can anyone think of cases where my second solution fails to find the missing term of an arithmetic progression? Code for my second solution is below.
import java.io.*;
import java.util.Vector;
public class Solution {
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int num = Integer.parseInt(br.readLine());
String[] numbers = br.readLine().split(" ");
Vector<Integer> ap = new Vector<Integer>();
for (String str: numbers){
ap.add(Integer.parseInt(str));
}
int first = ap.get(0);
int last = ap.get(ap.size()-1);
int incr = (last-first)/num;
for(int i = first; i<=last; i+= incr){
if(!ap.contains(i)){
System.out.println(i);
break;
}
}
}
}
Input Format The first line contains an Integer N, which is the number of terms which will be provided as input. This is followed by N consecutive Integers, with a space between each pair of integers. All of these are on one line, and they are in AP (other than the point where an integer is missing).
public class MissingAp
{
public static void main(String args[]){
int arr[] ={10,8,4,2,0,-2,-4,-6,-8,-10,-12};
int difference[]=new int[arr.length-1];
int missingTerm;
for(int i=1;i<arr.length;i++){
difference[i-1] = arr[i]-arr[i-1];
}
for(int j =0;j<arr.length-1;j++){
if(difference[j]!=difference[j+1]){
missingTerm = arr[j]+difference[j+1];
System.out.println("The missing term is: " + missingTerm );
break;
}}}}
This program will help you find missing term of an AP.
Wouldn't this fail if the sequence is decreasing instead of increasing?
If I had the numbers 10, 8, 4, 2, 0, the missing value would be 6.
You find increment of -10/5 = -2 properly.
But then the loop you start from i = 10, decrease by 2... as long asi <= 0. Well immediately i is > 0, so it'd exit the loop before decreasing at all. < only works if increasing.
So it's the i<=last statement that I think is the problem.
So you'd need seem kind of way to adjust the i<=last; statement based upon whether it is a positive or negative increment. I'm thinking it would have to do with absolute value and\or Math.signum, or including separate code section based upon a negative increment (not the fastest way, but reasonable). But I've never done much in Java, and you asked for how it failed. So hopefully there's your answer :-)
Sort the array to ensure that this works for any case.
Arrays.sort(input_array)
A JavaScript based solution for the same:
This has 2 cases:
CASE 1:
The array passed in has just one missing term, and the first and last
terms are not the missing ones. It definitely has a missing term.
In this case, we just need the array and use the basic school formula
sum of n terms = n/2 * (first + last)
function getMissingTerm(terms, n) {
var expectedSum = ((terms.length + 1)/2) * (terms[0] + terms[terms.length - 1]),
actualSum = 0;
for (var i = 0; i < terms.length; ++i) {
actualSum += parseInt(terms[i], 10);
}
return expectedSum - actualSum;
}
CASE 2:
The array passed does not have a missing term in itself
meaning the missing term is either the first or last term
In this case one must pass the length of the terms, n, which is greater than array length
function getMissingTerm(terms, n) {
var smallestDifference = Math.abs(terms[1] - terms[0]),
missingTerm = null;
for (var i = 2, diff; i < terms.length; ++i) {
diff = Math.abs(terms[i] - terms[i - 1]);
if (diff !== smallestDifference) {
missingTerm = diff < smallestDifference ? i : i + 1;
}
}
return (n && terms.length < n) ?
[terms[0] - smallestDifference, terms[n-2] + smallestDifference] : // return possible 2 terms, at the start and end of array
terms[0] + (missingTerm - 1) * smallestDifference; // return the missing term
}

Java reading in a string and converting numbers in strings into Integers types

I am trying to take numbers from a users string (if it has numbers) and convert those numbers to their numerical value. I have the following code which takes in user input.
Ex: java Convert "55s" will just output the number 55, which i will store for later usage
{
char Element = 0;
double Sum = 0;
boolean Check = false;
for(String s: args) // taking in user input for command line
{
for (int i = 0; i<s.length(); i++)
{
Check = true;
Element = s.charAt(i); // converting the string into chars
Sum = convert_to_numb (Element, Check);
Check = false;
}
}
The input is a string in which i separate into chars and send it to my conversion functions. The idea i have follows
public static double convert_to_numb (char elem, boolean check) //trying to convert chars to numbers
{
char iter = elem;
double number = 0;
int count = 0;
while (check == true)
{
number = number + (iter - 48) * Math.pow(10,count);
System.out.println(iter);
count ++;
}
return number;
}
Here I am feeding in the chars to see if they're numbers and convert the actual numbers into their integer value. To try to clarify i would like to perform the following task given an example input of "55" covert it to 5*10^1 + 5*10^0 = 55. I would appreciate any help. Thanks.
Alright, I think I might know what you're trying to accomplish, though as others have mentioned it is a little unclear.
To address the code you just posted, I don't think it'll behave the way you expect. For starters, the Boolean variable 'Check' accomplishes nothing at the moment. convert_to_numb is only called while Check is true, so it's redundant.
Additionally, the sum isn't being stored anywhere as you loop through the string. Every time you obtain a sum, it overwrites the previous one.
Your convert_to_numb method is even more troubling; it contains an infinite loop. Since Check is always set to 'true', you essentially have a while(true) loop that will never end.
I'm going to assume that your objective here is to parse whichever Strings are input into the program looking for groups of consecutive digits. Then you want to store these groups of digits as integers, perhaps in an array if you find multiple.
Something like this might do the trick.
{
ArrayList<Integer> discovered = new ArrayList<Integer>();
for (String s : args) {
// contains previous consecutive digits (if any)
ArrayList<Integer> digits = new ArrayList<Integer>();
for (int i = 0; i < s.length(); i++) {
Character c = s.charAt(i);
// add digit to digit array
if (c.isDigit()) {
digits.add(c.getNumericValue())
}
// not a digit, so we clear the digit array
else {
// combine the array to form an integer
if (! digits.isEmpty()) {
int sum = 0;
int counter = 0;
for (Integer i : digits) {
sum += i * Math.pow(10, counter);
counter++;
}
discovered.add(sum);
digits.clear();
}
}
}
}
}
Note the use of ArrayLists and the Integer and Character wrapper classes. These all provide functionality that helps deal with edge-cases. For example, I'm not sure that (iter - 48) part would have worked in all cases.
Something like this:
public static void main(String[] args) {
String string = "55s";
String[] piece = string.split("[\\D]+");
for (int j = 0; j < piece.length; j++) {
if(piece[j].trim().length() > 0) {
System.out.println(piece[j]);
}
}
}
It will split your initial string, the rest you should do yourself.

Java: Longest Ascending substring

I am trying to create a Java program that reads a numerical string typed from the keyboard,
and gives out the longest ascending substring.
The following is my code:
import java.util.Scanner;
public class Ascending{
public static void main(String args[]){
Scanner in = new Scanner(System.in);
System.out.print("Enter a number = ");
String n = in.nextLine();
int length = n.length();
for(int i = 0; i < length; i++) {
char first = n.charAt(i);
char next = n.charAt(i+1);
char last = n.charAt(length-1);
int f = (int)(first - 48);
int nx = (int)(next - 48);
int l = (int)(last - 48);
if (f<nx) {
String asc = n.substring(i, i++);
i++;
System.out.println("output = " + asc);
}
else {
String asc = n.substring(i, i++);
System.out.println("output = " + asc);
break;}
}
}
}
When I compile the above, I get
<Enter a number = 12 output = >
without any results.
I am assuming something went wrong inside the for-loop but I am unable to figure out where exactly I went wrong.
I'm afraid I might have defined too many unnecessary variables?
You are using the post-increment operator, but I don't think you have experimented to see how it works. Try this:
int i = 0;
System.out.println(i);
System.out.println(i++);
System.out.println(i);
You'll get
0
0
1
That's because post-increment (++) says "increment this value, then return what the value was before you incremented it".
So when you ask for
n.substring(i, i++);
You are explicitly asking for a 0-length string (because i == i++).
You could use the pre-increment operator, ++i, but it's rarely used outside of code-golf so you'll just end up confusing people. Best practice IMO is to just use ++ on its own line and avoid looking at the return value.
Really, what you want here is
n.substring(i, i+1);

Help with understanding java 'for' loops

I have to write a java program where the solution will include the printing of the arrow tip figure depending on the number of rows. Below are example of how the result should look. However, I cannot do this until I understand for loops. I know I have to work with the rows and columns and possibly nested loops. I just dont know how to connect the row with the columns using for loops. Please help me in understanding these loops. Thanks!
Example #1 (odd number of rows)
>
>>>
>>>>>
>>>>>>>
>>>>>
>>>
>
Example #2 (even number of rows)
>
>>>
>>>>>
>>>>>>>
>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>
>>>>>>>
>>>>>
>>>
>
a for loop will loop through a collection of data, such as an array. The classic for loop looks like this:
for(counter=0;counter <= iterations;counter++){ }
the first param is a counter variable. the second param expresses how long the loop should last, and the 3rd param expresses how much the counter should be incremented by after each pass.
if we want to loop from 1 - 10, we do the following:
for(counter=1;counter<=10;counter++){ System.out.println(counter); }
if we want to loop from 10 - 1, we do the following:
for(counter=10;counter>=1;counter--){ System.out.println(counter); }
if we want to loop through a 2 dimensional collection, like...
1 2 3
4 5 6
7 8 9
int[][] grid = new int[][] {{1,2,3},{4,5,6},{7,8,9}};
we need 2 loops. The outer loop will run through all the rows, and the inner loop will run through all the columns.
you are going to need 2 loops, one to iterate through the rows, one to iterate through the columns.
for(i=0;i<grid.length;i++){
//this will loop through all rows...
for(j=0;j<grid[i].length;j++){
//will go through all the columns in the first row, then all the cols in the 2nd row,etc
System.out.println('row ' + i + '-' + 'column' + j + ':' + grid[i][j]);
}
}
In the outer loop, we set a counter to 0 for the first parameter. for the second, to calculate how many times we will loop, we use the length of the array, which will be 3, and for the third param, we increment by one. we can use the counter, i, to reference where we are inside the loop.
We then determine the length of the specific row by using grid[i].length. This will calculate the length of each row as they are being looped through.
Please feel free to ask any questions you may have regarding for loops!
EDIT: understanding the question.....
You are going to have to do several things with your code. Here we will store the number of lines in a variable, speak up if you need to pass in this value to a method.
int lines = 10; //the number of lines
String carat = ">";
for(i=1;i<=lines;i++){
System.out.println(carat + "\n"); // last part for a newline
carat = carat + ">>";
}
The above will print out carats going all the way up. We print out the carat variable then we make the carat variable 2 carats longer.
.... the next thing to do is to implement something that will decide when to decrease the carats, or we can go up half of them and down the other half.
Edit 3:
Class Test {
public static void main(String[] args) {
int lines = 7;
int half = lines/2;
boolean even = false;
String carat = ">";
int i;
if(lines%2==0){even = true;} //if it is an even number, remainder will be 0
for(i=1;i<=lines;i++){
System.out.println(carat + "\n");
if(i==half && even){System.out.println(carat+"\n");} // print the line again if this is the middle number and the number of lines is even
if(((i>=half && even) || (i>=half+1)) && i!=lines){ // in english : if the number is even and equal to or over halfway, or if it is one more than halfway (for odd lined output), and this is not the last time through the loop, then lop 2 characters off the end of the string
carat = carat.substring(0,carat.length()-2);
}else{
carat = carat + ">>"; //otherwise, going up
}
}
}
}
Explanation and commentary along shortly. Apologies if this is over complicated (i'm pretty sure this is not even close to the best way to solve this problem).
Thinking about the problem, we have a hump that appears halfway for even numbers, and halfway rounded up for the odd numbers.
At the hump, if it is even, we have to repeat the string.
We have to then start taking off "<<" each time, since we are going down.
Please ask if you have questions.
I had the same question for a homework assignment and eventually came to a correct answer using a lot of nested if loops through a single for loop.
There is a lot of commenting throughout the code that you can follow along to explain the logic.
class ArrowTip {
public void printFigure(int n) { //The user will be asked to pass an integer that will determine the length of the ArrowTip
int half = n/2; //This integer will determine when the loop will "decrement" or "increment" the carats to String str to create the ArrowTip
String str = ">"; //The String to be printed that will ultimately create the ArrowTip
int endInd; //This integer will be used to create the new String str by creating an Ending Index(endInd) that will be subtracted by 2, deleting the 2 carats we will being adding in the top half of the ArrowTip
for(int i = 1; i <= n; i++) { //Print this length (rows)
System.out.print(str + "\n"); //The first carat to be printed, then any following carats.
if (n%2==0) { //If n is even, then these loops will continue to loop as long as i is less than n.
if(i <= half) { //This is for the top half of the ArrowTip. It will continue to add carats to the first carat
str = str + ">>"; //It will continue to add two carats to the string until i is greater than n.
}
endInd = str.length()-2; //To keep track of the End Index to create the substring that we want to create. Ultimately will determine how long the bottom of the ArrowTip to decrement and whether the next if statement will be called.
if((endInd >= 0) && (i >= half)){ //Now, decrement the str while j is greater than half
str = str.substring(0, endInd); //A new string will be created once i is greater than half. this method creates the bottom half of the ArrowTip
}
}
else { //If integer n is odd, this else statement will be called.
if(i < half+1) { //Since half is a double and the integer type takes the assumption of the one value, ignoring the decimal values, we need to make sure that the ArrowTip will stick to the figure we want by adding one. 3.5 -> 3 and we want 4 -> 3+1 = 4
str = str + ">>"; //So long as we are still in the top half of the ArrowTip, we will continue to add two carats to the String str that will later be printed.
}
endInd = str.length()-2; //Serves the same purpose as the above if-loop when n is even.
if((endInd >= 0) && (i > half)) { //This will create the bottom half of the ArrowTip by decrementing the carats.
str = str.substring(0, endInd); //This will be the new string that will be printed for the bottom half of the ArrowTip, which is being decremented by two carats each time.
}
}
}
}
}
Again, this was for a homework assignment. Happy coding.
Here is a simple answer for you hope it helps! Cheers Logan.
public class Loop {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
int count = i;
int j = 0;
while (j != count) {
System.out.print(">");
j++;
}
System.out.println();
}
for (int i = 10; i > 0; i--) {
int count = i;
int j = 0;
while (j != count) {
System.out.print(">");
j++;
}
System.out.println();
}
}
}
For making a 'for' loop:
public class Int {
public static void main(String[] args) {
for (Long num = 1000000L; num >= 9; num++) {
System.out.print("Number: " + num + " ");
}
}
}
Output:
Number: 1008304 Number: 1008305 Number: 1008306 Number: 1008307 ...

Categories

Resources