Write a Python function named first_recurring_character() or a JavaScript function named firstRecurringCharacter() that takes a string and returns either:
° The first recurring character in the given string, if one exists, or
° A null value like JavaScript’s or Kotlin’s null, Python’s None, or Swift’s nil.
Here’s the Swift version of my solution:
// Swift
func firstRecurringCharacter(text: String) -> String? {
var previouslyEncounteredCharacters = Set<Character>()
for character in text {
if previouslyEncounteredCharacters.contains(character) {
return String(character)
} else {
previouslyEncounteredCharacters.insert(character)
}
}
return nil
}
The Swift implementation differs from the Python and JavaScript versions due to Swift’s stricter typing
Swift’s Set requires you to specify the type of things that it will store. In this case, we want to store items of type Character.
When looping through the items in a string with a for loop in Swift, you get Character items. That’s why previouslyEncounteredCharacters stores Character items and not String items. Once the function detects the first recurring character, it converts that character into a string and returns that value.
Here’s the list of tech, entrepreneur, and nerd events for Tampa Bay and surrounding areas for the week of Monday, July 4 through Sunday, July 10, 2022.
Every week, with the assistance of a couple of Jupyter Notebooks that I put together, I compile this list for the Tampa Bay tech community.
As far as event types go, this list casts a rather wide net. It includes events that would be of interest to techies, nerds, and entrepreneurs. It includes (but isn’t limited to) events that fall under the category of:
Programming, DevOps, systems administration, and testing
Tech project management / agile processes
Video, board, and role-playing games
Book, philosophy, and discussion clubs
Tech, business, and entrepreneur networking events
Toastmasters (because nerds really need to up their presentation game)
Sci-fi, fantasy, and other genre fandoms
Anything I deem geeky
By “Tampa Bay and surrounding areas”, this list covers events that originate or are aimed at the area within 100 miles of the Port of Tampa. At the very least, that includes the cities of Tampa, St. Petersburg, and Clearwater, but as far north as Ocala, as far south as Fort Myers, and includes Orlando and its surrounding cities.
StartupBus 2022 will depart from Tampa Bay!
If you’re looking for an adventure, a chance to test your startup skills, and an experience that will make your résumé stand out, join me on StartupBus Florida, which departs Tampa Bay on July 27, when it sets course for Austin, Texas!
On this three-day journey, “buspreneurs” will form teams, create a business idea, build a software demo for that idea, and develop pitches for that idea. When they arrive in Austin, they’ll spend two days pitching their startups to a panel of judges.
I was a “buspreneur” on StartupBus Florida in 2019, the last time the event took place, and our team made it to the finals and got the runner-up position. This time, I’m a “conductor” — one of the coaches on the bus — and our team is here to help you rise to the challenge.
If you’d like to get this list in your email inbox every week, enter your email address below. You’ll only be emailed once a week, and the email will contain this list, plus links to any interesting news, upcoming events, and tech articles. Join the Tampa Bay Tech Events list and always be informed of what’s coming up in Tampa Bay!
If you had an application or script that uses Selenium and ChromeDriver to control or automate instances of Chrome or Chromium, it’s probably not working right now. Instead, you’re probably seeing error messages that look like this:
Message: unknown error: cannot determine loading status
from unknown error: unexpected command response
(Session info: chrome=103.0.5060.53)
Stacktrace:
0 chromedriver 0x000000010fb6f079 chromedriver + 4444281
1 chromedriver 0x000000010fafb403 chromedriver + 3970051
2 chromedriver 0x000000010f796038 chromedriver + 409656
...and on it goes...
ChromeDriver 103 — or more accurately, ChromeDriver 103.0.5060.53 — works specifically with Chrome/Chromium 103.0.5060.53. If you regularly update Chrome or Chromium and use ChromeDriverManager to keep ChromeDriver’s version in sync with the browser, you’ve probably updated to ChromeDriver 103.0.5060.53, which has a causes commands to ChromeDriver to sometimes fail.
The fix
Luckily, the bug has been fixed in ChromeDriver 104, which works specifically with Chrome 104. This means that if you update to Chrome and ChromeDriver 104, your Selenium / ChromeDriver / Chrome setup will work again.
The challenge is that Chrome 104 is still in beta. As I’m writing this, the Google Chrome Beta site is hosting an installer for Chrome 104, or more accurately, Chrome 104.0.5112.20. The application has the name Google Chrome Beta and is considered a separate app from Google Chrome. This means that you can have the current release and the beta version installed on your machine at the same time.
Once you’ve installed Chrome Beta, you just need to make your Selenium/ChromeDriver application or script use the appropriate version of ChromeDriver. Here’s how I did it in Transmogrifier, my Python script that helps me assemble the Tampa Bay Tech Events list:
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
// 1
option = Options()
option.binary_location='/Applications/Google Chrome Beta.app/Contents/MacOS/Google Chrome Beta'
// 2
driver = webdriver.Chrome(service=Service(ChromeDriverManager(version='104.0.5112.20').install()), options=option)
Here are some explanation that match the number comments in the code above:
These lines create an instance of the Options class, which we’re using to specify the directory where the Chrome beta app can be found. We’ll use the instance, options, when we create driver, the object that controls the Chrome beta app.
This constructor creates a WebDriver.Chrome object which will control the Chrome beta app. The service parameter specifies that the driver should be an instance of ChromeDriver 104, and that it should be installed if it isn’t already present on the system. The options parameter specifies that ChromeDriver should drive the version of Chrome located at the directory path specified in the option object: the Chrome beta app.
Once that’s done, I can proceed with my script. Here’s a simplified version of the start of my Transmogrifier script:
from bs4 import BeautifulSoup
// Load the web page whose URL is `url` into
// the browser under script control
driver.get(url)
// Execute any scripts on the page so that
// we can scrape the final rendered version
html = driver.execute_script('return document.body.innerHTML')
// And now it’s time to scrape!
soup = BeautifulSoup(html, 'html.parser')
// ...the rest of the code goes here...
The title of this post should be a big hint: Everything you need to know in order to win StartupBus North America 2022 is contained within a podcast. This is the third in a series of posts covering the “Startup Bus” series of episodes from Gimlet Media’s Startup podcast, which covered the New York bus’ journey during StartupBus 2017.
Did you miss the first four articles in this series? Here they are:
…and here are the lessons I took away from this episode:
A lot of what makes success is just showing up. At the start of the episode, podcast host Eric goes for an early morning walk with Colleen Lavin of team Daisy and discovers that she was nce the Illinois Knights of Columbus free throw champion for girls age 14. Here’s how she tells the story:
COLLEEN: I was like getting my school volunteer hours, helping my dad at the free throw contest, and I was in the right age range, so he made me compete. I made two baskets, because I was not a basketball player. But no other girls in my age range showed up, and he made me go to the next competition and no other girls my age range showed up. Finally, I was almost sent to D.C to compete in the nationals after making a total of like four baskets.
ERIC: Because nobody had showed up?
COLLEEN: In my age competition!
Be prepared for possible twists in the finals.Elias Bizannes, the creator of StartupBus, loves drama. In the 2017 competition, even though there were five finalists, Elias decided to create a sixth team made up of people from teams who didn’t make it into the finals. The team would create a blockchain-powered voting app. Why did he do it? In his own words…
To mess with people to be honest. Because that’s what we do with StartupBus, we push them and we break them. And what happens is this remarkable thing comes out when people go beyond the limits they think they can, they actually step up. And so by introducing a new team, it was gonna add another level of competitive threat to the finals.
The finals will feature far more polished pitches and apps: “From the moment the pitches begin, it’s apparent. This is a very different level of competition than yesterday. The presentations are all well-crafted. Each of the products makes sense. You could imagine people making these pitches to actual investors.”
Are you interviewing for job that involves coding or requires coding skills? Then it’s very likely that you’ll be asked to undergo a coding test in the interview.
A long while back, I very badly embarrassed myself in an interview with Google. A Googler friend referred me (referrals are always better than applying yourself) and a handful of days later, I was in the interview, and I did everything wrong. I promised myself that I would never embarrass myself with such a pitiful coding performance at an interview again, and I’d also like to help ensure that it never happens to you either.
The trick, of course, is to practice. In this series, How to solve coding interview questions, I’ll walk you through the sort of questions that you might be asked in a coding interview. Many of the questions you’ll be asked will involve the sort of things that get covered in a “Algorithms and data structures” class and will be designed to test your general problem-solving ability. I’ll show you a solution, and where applicable, I’ll show you some alternate solutions and discuss the pros and cons of each.
You should try coming up with your own answers before looking at mine — after all, it’s the best way to learn!
The “first recurring character” function
This is a classic coding interview question that is often presented to junior developers.
The challenge
Write a Python function named first_recurring_character() or a JavaScript function named firstRecurringCharacter() that takes a string and returns either:
The first recurring character in the given string, if one exists, or
A null value like JavaScript’s or Kotlin’s null, Python’s None, or Swift’s nil.
Here are some example inputs for first_recurring_character(), along with what their corresponding outputs should be:
If you give the function this input…
…it will produce this output:
'abcdeefg'
'e'
'abccddee'
'c'
'abcde'
null / None / nil
One solution
See if you can code it yourself, then scroll down for my solution.
👇🏽
👇🏽
👇🏽
👇🏽
👇🏽
👇🏽
👇🏽
👇🏽
👇🏽
👇🏽
👇🏽
👇🏽
👇🏽
👇🏽
👇🏽
👇🏽
👇🏽
👇🏽
👇🏽
👇🏽
👇🏽
If you had to perform the function’s job yourself, you’d probably go through the given string character by character and use a piece of paper to jot down the keep track of the characters you’ve already seen.
Here’s a solution that takes this approach, in Python:
def first_recurring_character(text):
previously_encountered_characters = []
for character in text:
if character in previously_encountered_characters:
return character
else:
previously_encountered_characters.append(character)
return None
Here’s the JavaScript version:
function firstRecurringCharacter(text) {
let previouslyEncounteredCharacters = []
for (const character of text) {
if (previouslyEncounteredCharacters.includes(character)) {
return character
} else {
previouslyEncounteredCharacters.push(character)
}
}
return null
}
Both do the following:
They use a built-in data structure to keep track of characters that they have previous encountered as they go through the given string character by character. In the Python version, the data structure is a list named previously_encountered_characters; in the JavaScript version, it’s an array named previouslyEncounteredCharacters.
The use a loop to go through the given string one character at a time.
For each character in the given string, the program checks to see if the current character has been encountered before:
If the current character has been encountered before, it’s the first repeated character. The function returns the current character.
If the current character has not been encountered before, it is added to the data structure of previously encountered characters.
If the function goes through the entire string without encountering a previously encountered character, it returns a null value (None in Python, null in JavaScript).
What’s the Big O?
If you’ve made it this far, you might be asked how you can improve the code. This is a different question in disguise: You’re actually being asked if you know the computational complexity or “The Big O” for your solution.
First, there’s the for loop. For a given string of length n, the worst-case scenario — either the string doesn’t have any recurring characters or the recurring character is at the very end — the loop will have to execute n times. That task’s complexity of O(n).
Next, let’s look inside the for loop. There’s a test to see if the current character is in the collection of previously encountered characters. In Python, this test is performed by the in operator; in JavaScript, it’s performed by the includes() method.
Python’s TimeComplexity page says that using the in operator to find an item in a list is an O(n) operation on average.
That’s because they both use the following algorithm to determine if a given item is in a list or array:
if we are not yet past the last item in the list/array:
get the next item in the list/array
if this item is the one we’re looking for:
return true
if we are at this point and we have not found the item:
return false
So the function is basically an O(n) operation performing an O(n) operation on average, effectively making it an O(n2) operation. As far as computational complexity goes, this is considered “horrible”:
Tap to view at full size.
Can you improve the code?
You’ve probably figured out that the way to improve the code is to try and reduce its time complexity.
You probably can’t reduce the time complexity of the for loop. The function has to find the first recurring character, which means that it needs to go through the characters in the given string in order, one at a time. This part of the function will be stuck at O(n).
But you might be able to reduce the time complexity of check to see if the current character in the loop has been encountered before. In the function’s current form, we’re using a Python list or JavaScript array to keep track of characters that we’ve encountered before. Looking up an item in in these structures is an O(n) operation on average.
The solution is to change the data structure that keeps track of previously encountered characters to one where looking for a specific item is faster than O(n). Luckily, both Python and JavaScript provide a data structure for sets, where the time to look up an item is generally O(1).
Let’s rewrite the function to use sets. Here’s the Python version:
def first_recurring_character(text):
previously_encountered_characters = set()
for character in text:
if character in previously_encountered_characters:
return character
else:
previously_encountered_characters.add(character)
return None
The Python version doesn’t require much changing. We simply changed the initial definition of previously_encountered_characters from an empty array literal ([]) to a set constructor and call on set’s add() method instead of the append() method for arrays.
Here’s the JavaScript version:
function firstRecurringCharacter(text) {
let previouslyEncounteredCharacters = new Set()
for (const character of text) {
if (previouslyEncounteredCharacters.has(character)) {
return character
} else {
previouslyEncounteredCharacters.add(character)
}
}
return null
}
The JavaScript version requires only a little more changing:
The initial definition for previouslyEncounteredCharacters was changed to a Set constructor.
We changed the array includes() method to the set has() function.
We also changed the array push() method to the set add() method.
Changing the data structure that stores the characters that we’ve encountered before reduces the complexity to O(n), which is much better.
Coming up next
In the next article in this series, we’ll tackle a slightly different problem: Can you write a function that returns the first non-recurring character in a string?
The title of this post should be a big hint: Everything you need to know in order to win StartupBus North America 2022 is contained within a podcast. This is the third in a series of posts covering the “Startup Bus” series of episodes from Gimlet Media’s Startup podcast, which covered the New York bus’ journey during StartupBus 2017.
…and here are the lessons I took away from this episode:
If you can find teammates that are on your wavelength, you can achieve a lot. Although they’re on the Florida StartupBus and not the bus that the podcast is covering, they remain a source of fascination for Eric, the host. Not only do Robert Blacklidge and Trey Steinhoff get along so well, but they also work so well together, and the synergy will take them far together. (Full disclosure: I worked with Trey at Lilypad, and can vouch for the fact that he is a great teammate. I also know Robert and can understand why he and Trey got along so well.)
A conflict within the team doesn’t have to destroy the team; in fact, not only can conflicts be resolved, but they can even strengthen a team. Ash from the Denari team had rubbed many of his teammates the wrong way, and there was talk of kicking him off the team. Things have turned around in this episode: everyone’s getting along, and Ash is considerably less acerbic — even optimistic-sounding.
The StartupBus format borrows some of its ideas from reality TV game shows, which means that there can be intentional confusion. “The teams have been getting different information about the competition all day. They’re hearing conflicting things about timing, about whether or not pitch decks are allowed. And this confusion, it all feels weirdly intentional.”
StartupBus is supposed to be a challenge. It’s not supposed to be easy, and as anyone who’s done it before will tell you, it can be gruelling at times. And that’s a good thing — if StartupBus works as designed, you shouldn’t be exactly the same person at the end of the ride. As one of the Denari people puts it: “This is a Navy SEAL training program for startups. This is like we’re going to push you to that to the limit of your mental strength, like every single person on their team is that like living in a role that’s very different from what they walked on the bus wanting to do.”
Speaking about come out of StartupBus a little different, you can see some of the buspreneurs’ change — they’re more certain, more directed, more convinced of their ability to change their personal course through life.
You can most definitely incorporate singing and music in your pitch. The pitch for singing telegram startup Yeti featured one of their buspreneurs in a full Marilyn Monroe costume, singing Katy Perry’s Firework, but with StartupBus-specific lyrics. I also did that with the accordion at StartupBus 2019.
You can also use audience participation in your pitch. Tampa-based CourseAlign did that by asking the audience for a show of hands, using questions that would get a specific kind of result.
Be ready for tough questions. During the Q&A section of their pitch, Denari — the Blockchain-powered GoFundMe-like startup — is asked how they plan to prevent their system from being turned into a money-laundering platform.
Don’t be too hard on yourself. After getting that tough money-laundering question, Colleen Wong, who’s been leading Denari, felt bad about her answer and said that she didn’t feel that she was a good leader. Eric the host had to reminder her that she did the near-impossible — “Are you kidding me?! Have you, like, seen yourself this week?! …You, like, pulled together the, like, craziest team on the bus. It was a great thing.”
Anything can happen in the judging room. Eric the host was invited into the judging room to record a reenactment of judges’ discussion as they tried to decide who would move the next round. But as they reenacted their discussion, they started changing their minds. The judging process can turn on a dime.
There is a downside to making it into the finals: It means that although you’re in a party town, you can’t party. You’re going to be working on your product and your pitch for the finals. Trust me on this one — I was in New Orleans, one of the best party towns in the country, and I spent Saturday night with my team working on our startup.
Arguing Agile is new addition to this list, and it’s also the newest podcast on this list. Hosted by Brian Orlando and Om Patel, two mainstays of the Tampa Bay agile community and familiar faces at local agile events, this podcast features discussions — sometimes just between the hosts, sometimes with a local guest — and they cover all sorts of subjects, all centered around the process of making software in a timely fashion.
Their podcast has been around only a year, but Brian and Om have been absolute podcasting powerhouses, cranking out nearly 70 full episodes in that time, covering such topics as:
If you’re on a software team and you’re looking for ways to improve the way you and your team get things done, you’ll want to check out Arguing Agile.
Here are their 5 most recent episodes:
Episode 67: Team Topologies: Organizing Business and Technology Teams for Fast Flow — On this episode, Product Manager Brian Orlando pitches Enterprise Agile Coach Om Patel on the team optimization suggestions from the book, Team Topologies: Organizing Business and Technology Teams for Fast Flow (2019), by Matthew Skelton and Manuel Pais.
Episode 66: Personal Agility & the Great Resignation, with Joey deVilla — When we think about unmitigated optimism and unwavering positivity, we think of none other than the unflappable – Joey deVilla! On this episode, we talk about how the great resignation has affected us and how a commitment to personal agility helps people and companies through tough times.
Episode 65: A Better Sprint Review Agenda — Does a perfect Sprint Review agenda exist? On this episode, Brian Orlando and Om Patel ask this very question and try to figure it out! Using some original content from one of our favorite Agile Coaches out there, Vibhor Chandel, we review, discuss, and revise our way toward a Sprint Review agenda that we are excited to try with our teams, and that we hope you’ll try with yours.
Episode 64: Bad Agile Experiences, with Curtis Lembke — What creates bad experiences with agile; what do they look like, and how to we deal with them? On this episode of Arguing Agile, Curtis Lembke is back, joining Brian Orlando and Om Patel to talk through Bad Agile Experiences and why some people just totally against agile.
Episode 63: Get More Value from Your Scrum — Do you feel Scrum is not helping you to more effectively create software or solve problems? Do you feel Scrum is just another form of managerial control? Do you feel Scrum is not helping your organization be or remain agile? On this episode, Brian Orlando and Om Patel discuss experiences and share tips to make scrum more effective – thereby producing more value.
Space and Things is the newest podcast on this list, and it’s probably the most comprehensive podcast about space science, research, and exploration. It’s hosted by Emily Carney of Space Hipsters fame, and singer/songwriter/space fan Dave Giles.
STP92 – ‘For All Mankind’ Season 3 Preview – with Krys Marshall — This week we’re joined by one of the stars of AppleTV’s ‘For All Mankind’ – the one and only Krys Marshall who plays Danielle Poole. Season 3 premieres on June 10th, so this is a perfect time for a look back at seasons 1 and 2, plus a little preview into season 3, but don’t worry, there are no season 3 spoilers.
STP91 – Becoming Off-Worldly – with Laura Forczyk — This week we’re joined by Laura Forczyk to discuss her new book: Becoming Off-Worldly: Learning From Astronauts To Prepare For Your Spaceflight Journey.
…a show dedicated to helping developers to grow their career. Topics include Test Driven Development, Clean Code, Professionalism, Entrepreneurship, as well as the latest and greatest programming languages and concepts.
Here are their 5 most recent episodes:
Episode 245: Releasing Software with Tommy McClung — A software engineer by trade and multiple time entrepreneur, Tommy was the CTO at TrueCar for a number of years and is Co-founder and CEO of Release.
Episode 244: Eric Potter on F# and .NET Interactive Notebooks — Eric helps companies succeed by finding the right custom software solutions to their business problems. He has been a Microsoft MVP since 2015, and is currently Director of Technical Education at Sweetwater.
Episode 242: Temporal with Maxim Fateev & Dominik Tornow — Maxim has worked at companies such as Microsoft, Google, and Amazon, and is currently CEO and cofounder of Temporal. Dominik is a Principal Engineer at Temporal. He focuses on systems modeling, specifically conceptual and formal modeling, to support the design and documentation of complex software systems.
Episode 241: gRPC in .NET 6 with Anthony Giretti — Anthony is a passionated developer, Microsoft MVP, and MCSD. He is currently senior developer @ Sigma-HR, specializing in Web technologies. We’re giving away several copies of Anthony’s new book, “Beginning gRPC with ASP.NET Core 6”. Leave a comment below for your chance to win!
Of the podcasts in this roundup, Thunder Nerds — “A conversation with the people behind the technology, that love what they do… and do tech good” — has been around the longest, with nearly 300 episodes to date. You’ve probably seen the hosts at local meetups and conferences; they’re Frederick Philip Von Weiss, Brian Hinton, and Vincent Tang.
Thunder Nerds is sponsored by a company that’s near and dear to me, Auth0! That’s partly because they have a great authentication, authorization, and identity service, and partly because I work there in my role as a Senior Developer Advocate!
293 – 💻 Remote Work & Top Talent With Zack Gottlieb — We talk with Zack Gottlieb, VP Head of Design platform at Atlassian. We discuss Zack’s career journey and what it takes to make it to Atlassian. Our main topic of discussion is the Great Resignation in the tech industry. We start the conversation by asking why so many people are leaving in the first place. Then we explore why companies want their employees back in the office. Additionally, we examine what companies are doing to retain their top talent.
292 – 🎯 Paid Media Strategies with Michelle Morgan — In this episode, we talk with Michelle Morgan: International Paid Media Consultant, Writer, and Speaker. We explore the realm of advertising on the most popular social platforms and investigate the unforeseen opportunities in others. Additionally, we discuss Michelle’s organization, Paid Media Pros, which provides PPC videos for advertisers with any level of experience.
290 – 🎵 Little Music Boxes with Travis Neilson — In this episode, we talk with designer, musician, Travis Neilson. We discuss Travis’s career at YouTube Music. We dive into his day-to-day and what it’s like to work at YouTube. Then we explore Travis’s music, specifically his channel Little Music Boxes.
289 – ⚱️ The Digitization of Deathcare with Faisal Abid — In this episode, we talk with Faisal Abid: Speaker, Entrepreneur, Google Developer Expert, and co-founder of Eirene cremations. Eirene provides high-quality, affordable cremation services. Eirene allows families to plan an affordable cremation entirely online or over the phone. Leveraging technology to help provide a better funeral experience to families. Additionally, Faisal walks us through the unique business and technology challenges he faced at the beginning of Eirene.