How to print specific numbers from a for loop using Kotlin - android

So I am fairly new to Kotlin and I need to generate specific numbers from a for loop of 1 to 13.
For the first output I need only odd numbers
For the second output I need numbers 2, 5, 8, 11, 14, 19 and 20 from a for loop of 0 to 20
For starters I can print an entire list using:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
for (i in 1..13){
println(i)
}
}
}
But that's it. What do I need to print the other required outputs?

Once you know how to write a for loop that prints every number, the question becomes how to identify a number that you "should" print from a number that you should not.
Your first sequence is all odd numbers, so #DipankarBaghel's answer covers that. Your second sequence seems to be all numbers for which the remainder when dividing by 3 is 2. (Except 19; did you mean 17 for that one?)
You can use the same operator in this case, but instead of checking for 0 (or for != 0) you can check that the remainder is 2:
for (i in 0..20) {
if (i % 3 == 2) {
println(i)
}
}
The key concept here is that of %, the remainder operator (sometimes called the modulo operator). The result of x % y will be the remainder when x is divided by y. Odd numbers have a remainder of 1 when divided by 2, so i % 2 == 1 will be true only for (positive) odd numbers.

To check even you need to do i%2==0 and for odd just check i%2!=0.
for (i in 1..13){
if(i%2!=0){
println("odd number "+i);
}
if(i%2==0){
println("even number "+i);
}
}
Hope this will help you.

To generate Odd numbers:
for (i in 1..13) {
if(i % 2 == 1 ){
println(i + ", ");
}
}
To Generate 2, 5, 8, 11, 14, 19 and 20:
for (i in 0..20) {
if (i % 3 == 2) {
println(i + ", ");
}
}

Related

How to get longest streak from an array of int Kotlin

I am working on a story and am wondering how I can solve this problem similar to my current work at work, so a weekly streak is defined as one or more consecutive active weeks in which a user has worked out. So say you are given an array of active user days, we need find the length of the longest active weekly streak.
Here each element in the array represents an offset from an arbitrary Monday in the calendar (e.g. Thursday Feb 4th 2022).
The offsets are zero indexed.
Some helpful tips are:
Active day there is at least one exercise for the user during a calendar day
Active week is a calendar week, starting on a Monday, with at least one active day for a user
Weekly streak being One or more weeks (consecutive) active weeks in a user's workout history
The length of the streak is defined as the number of active weeks in the streak
Here is my code:
val str1 = arrayOf(9, 14, 365, 366, 367) //2
val str2 = arrayOf(2, 22, 29, 37, 43, 366, 391) //4
fun findLongestStreak(callDays: Array<Int>): Int{
}
What is the simplest way to write this function I have been stuck for a week now?
You could do it like this
val str1 = arrayOf(9, 14, 365, 366, 367) //2
val str2 = arrayOf(2, 22, 29, 37, 43, 366, 391) //4
fun toWeek(day: Int) = day / 7
fun activeWeeks(days: Array<Int>) = days.map(::toWeek).toSet().sorted()
// find runs of consecutive numbers in a list of integers,
// and return a list of those runs' lengths
fun getStreaks(nums: List<Int>): List<Int> =
if (nums.isEmpty()) emptyList()
// We're going to iterate over each adjacent pair of numbers, so we can check
// if the second number immediately follows the first, so we can add to
// the current streak.
// Since we're looking at the second number in each pair, the first in the list
// (we know there's at least one) is a special case - so we start the list
// we're building up with a streak of 1, representing that first number
else nums.zipWithNext().fold(mutableListOf(1)) { streaks, (prev, current) ->
streaks.apply {
// if the second number (the one we're checking) follows the first,
// add 1 to the most recent streak length in the list
if (current == prev + 1) streaks[lastIndex] += 1
// if they're not consecutive, we need to start a new streak for this number
else streaks.add(1)
}
}
fun findLongestStreak(callDays: Array<Int>): Int =
callDays.run(::activeWeeks)
.run(::getStreaks)
.run { maxOrNull() ?: 0 }
That's mostly explanation - basically I'm converting all the day numbers into their corresponding week numbers, using toSet() to remove duplicates and sorted to turn that into a List of ascending week numbers
Then the fold function starts with a streak of 1 for the first week number, then goes through the rest of them, comparing each to the previous week number. If it's consecutive, add 1 to the current streak. If it's not, start a new streak of length 1. (If you don't like the fold, you could just do a for loop with the same logic)
That way you end up with a list of streak lengths and you can just grab the longest one
The code is based on the idea that consecutive weeks minus their position index in the array lead to the same (meaningless) number, while with two non-consecutive weeks the two numbers will be different:
val str1 = arrayOf(9, 14, 365, 366, 367)
val str2 = arrayOf(2, 22, 29, 37, 43, 366, 391)
fun findLongestStreak(callDays: Array<Int>): Int {
return callDays
.map { it / 7 } // [1, 2, 52, 52, 52]
.toSet() // [1, 2, 52]
.mapIndexed { index, i -> i - index } // [1, 1, 50]
.groupBy { it } // {1=[1, 1], 50=[50]}
.maxOf { it.value.count() } // 2
}
println(findLongestStreak(str1)) // 2
println(findLongestStreak(str2)) // 4
You can use a Set that has a unique values for the workout weeks. Then filter the set with non-consecutive weeks (the idea is that for an arbitrary day, it should not belong to a week that is just equals to the previous day's week + 1);
Eventually, the size of the outcome is what you need (the active discrete weeks):
UPDATE:
Simplifying with toSet() instead of the for loop to be more linear:
fun findLongestStreak(callDays: Array<Int>) = callDays.map { it / 7 }.toSet()
.let { it.filter { day -> !it.contains(day - 1) } }.size
Original answer:
fun findLongestStreak(callDays: Array<Int>): Int {
val workoutWeeks = mutableSetOf<Int>() // all the workout weeks
for (day in callDays) workoutWeeks.add(day / 7)
return workoutWeeks.filter { !workoutWeeks.contains(it - 1) }.size
}
Notice that the day / 7 returns the week number offset similarly referring as they are offset to the base Monday.

kotlin - Problem with my if statement and operator

This is my goal : user click on minus button the amount decrease by one and there is a if statement to not allow the amount go lower than 0 .
This is my Code :
var number = 0
view.text_amount.visibility = View.GONE
view.plus_btn.setOnClickListener {
if (number == 5) {
Toast.makeText(
requireContext(),
"Limit in order",
Toast.LENGTH_SHORT
).show()
} else {
view.text_amount.visibility = View.VISIBLE
number++
view.text_amount.text = number.toString()
}
}
view.minus_btn.setOnClickListener {
if (number <= 0) {
view.text_amount.visibility = View.GONE
} else {
number--
view.text_amount.text = number.toString()
}
}
there is problem with code : I don't want the amount be visible after getting to 0 . it's better experience when the amount is equal to 0 not be visible .
I think it has a simple solution but I can't see it .
do you have any idea ?
Your code works fine! If you want to make it simpler, there's a bit of repeated logic you could condense into one function that handles the situations:
fun adjustValue(amount: Int) {
val adjusted = number + amount
if (adjusted > 5) // show Toast
number = adjusted.coerceIn(0, 5)
view.text_amount.text = number.toString()
view.text_amount.visibility = if (number == 0) View.GONE else View.VISIBLE
}
view.minus_btn.setOnClickListener { adjustValue(-1) }
view.plus_btn.setOnClickListener { adjustValue(1) }
basically the idea is you work out the new value (I'm using a temporary variable so we never set number to an invalid value) and show whatever warnings you need to. Then the coerceIn line makes sure we lock it within the valid range of allowed values.
You could do if/else checks and only set the new value if it's a valid one, but sometimes it's simpler and shorter to just set things and then worry about the edge cases, so this is just an example of that!
Same thing for the TextView bit - it's easier to just set the value whatever it is, and then set whether it should be displayed or not. You could use if/else branches to look at the value and decide whether to set the text or not... but why make your life hard? We know the value's in the valid 0 to 5 range, we can hide it if it's 0 and show it otherwise... easy!
You could make the function take a Boolean instead, like plus: Boolean and then go val adjusted = number + if (plus) 1 else -1, but making it an Int means you could easily add a +10 button or whatever without adding any more code or any more validation logic, and it's not any more complicated to pass in -1 instead of false (arguably it's clearer!)
that's probably more than you were asking for but hopefully it's useful. If nothing else, the "just set the text and the visibility every time" approach is good and neat
Decrease the value of text_amount only if it contains a value greater than 0 and after that check again its value and if it is 0 then hide it:
view.minus_btn.setOnClickListener {
if (number > 0) {
number--
view.text_amount.text = number.toString()
if (number == 0) view.text_amount.visibility = View.GONE
}
}

Iterating over list with lambda forEach Kotlin

I have a list of 30 random numbers that correspond to 1 of 8 colours, and I need to iterate over the 8 colors(or 30 numbers) and find the number of times each colour occurs. I need to do this using lambdas and functional programming, so no traditional for loops.
val iterator = colours.toList().iterator()
iterator.forEach{
println("$it count: " + (numbers
.map{a -> colours[a]}
.count{it == ("$it")}))
}
The problem currently is my output for count is just 50, not the specific number of times a colour occurs.
If I do it like this:
println("Red count:" + (numbers
.map{a -> colours[a]}
.count{it == ("red")}))
it outputs the correct number, but not with the loop.
What it ouputs:
green count: 50
red count: 50
what it should output (for example)
green count:9
red count:3
Thanks in advance
Add a named parameter to your forEach loop. The implicit name "it" is getting shadowed by the count function.
val iterator = colours.toList().iterator()
iterator.forEach { colour ->
println("$colour count: " + (numbers
.map{a -> colours[a]}
.count{it == ("$colour")}))
}
You don't really need to do a nested iteration here. Currently you're operating at O(n^2) since you have to traverse the list once for every element. Since you know you're working with a small number of potential values, you could instead just group them by value and then map the values to the size of the resulting lists, i.e.
val colourNames = listOf("red", "green", "blue", "yellow", "orange", "indigo", "violet", "black")
// Generates 30 random numbers between 0 and 8 (exclusive)
val randomColours = (0 until 30).map { (0 until colourNames.size).random() }
val result = randomColours
.groupBy { color -> colourNames[color] } // outputs a Map<String, List<Int>>
.mapValues { (color, colorCountList) -> colorCountList.size } // Map<String, Int>
println(result) // {yellow=4, orange=4, red=5, indigo=3, blue=8, green=2, violet=2, black=2}

Android- method is permanently changing the value of variable

I have this method which I dont understand.
2 global variables which are important for this questions:
-mNextButton;
-mCurrentIndex;
mNextButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mCurrentIndex = (mCurrentIndex + 1) % mQuestionBank.length;
int questionID = nameOfArray[mCurrentIndex].getQuestion();
mQuestionTextView.setText(question);
}
});
how is it possible that mCurrentIndex is increased permanently every time user clicks mNextButton?
Try to be more specific. What do you really what to know?
In your code you setup a callback, which will be called, when user press the button. Inside that code you updating your "global" variables (since java has no global variables, I will assume you mean class field variable inside activity)
mCurrentIndex = (mCurrentIndex + 1) % mQuestionBank.length;
this will update mCurrentIndex exactly as specific - it increase the index for one, and fold it, when the value increase more than mQuestionBank.length. % is a standard modulo operator.
For gaining more understanding check out your mQuestionBank.length parameter or write a better question. Good luck.
For solving this you need to set one local variable. So in your onClick method:-
int mCIndex = mCurrentIndex;
mCIndex = (mCIndex + 1) % mQuestionBank.length;
int questionID = nameOfArray[mCIndex].getQuestion();
mQuestionTextView.setText(question
);
Thats it
The value of mCurrentIndex is set to the value of
(mCurrentIndex+1) % mQuestionBank.length
with every click on mNextButton.
This value is depending on the mCurrentIndex and the length of mQuestionBank. To explain the operation, take a look at the modulo operator:
https://en.m.wikipedia.org/wiki/Modulo_operation
To cut it short:
If mCurrentIndex for example has a value of 4, it's incremented by 1 and you get 5.
Now, it's depending on the length of your mQuestionBank. If it's 2000 it will have 0-1999 residual classes. Every number that you modulo by 2000 will fall into one of these classes.
So if you do the operation 0 mod 2000 equals 0, because 0 divided by 2000 has no remainder.
1 mod 2000 is 1 because 1 divided by 2000 is 0 with a remainder of 1. And 5 mod 2000 will be equal to 5.
In your case: mCurrentIndex will increase with every click until
mCurrentIndex+1 = mQuestionBank.lenght
because then it will start with 0 again. Since, in this example, 2000 mod 2000 is 1 with no remainder.

Determining even/odd numbers (integers)?

I feel stupid asking such a simple question, but is there an easy way to determine whether an Integer is even or odd?
if ((n % 2) == 0) {
// number is even
}
else {
// number is odd
}
It's not android specific, but a standard function would be:
boolean isOdd( int val ) { return (val & 0x01) != 0; }
Many compilers convert modulo (%) operations to their bitwise counterpart automatically, but this method is also compatible with older compilers.
You can use modular division (technically in Java it acts as a strict remainder operator; the link has more discussion):
if ( ( n % 2 ) == 0 ) {
//Is even
} else {
//Is odd
}
If you do a bitwise-and with 1, you can detect whether the least significant bit is 1. If it is, the number is odd, otherwise even.
In C-ish languages, bool odd = mynum & 1;
This is faster (performance-wise) than mod, if that's a concern.
When somehow % as an operator doesn't exist, you can use the AND operator:
oddness = (n & 1) ? 'odd' : 'even'
Similar to others, but here's how I did it.
boolean isEven = i %2 ==0;

Categories

Resources